首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分析冒号分隔的数据

分析冒号分隔的数据
EN

Stack Overflow用户
提问于 2013-10-15 22:43:20
回答 3查看 641关注 0票数 0

我有以下文本块:

代码语言:javascript
复制
string = """
    apples: 20
    oranges: 30
    ripe: yes
    farmers:
            elmer fudd
                   lives in tv
            farmer ted
                   lives close
            farmer bill
                   lives far
    selling: yes
    veggies:
            carrots
            potatoes
    """

我正在试图找到一个好的正则表达式,它将允许我解析出键值。我可以通过这样的方法获取单行键值:

代码语言:javascript
复制
'(.+?):\s(.+?)\n'

然而,当我碰到农民或蔬菜时,问题就来了。

使用re标志,我需要执行如下操作:

代码语言:javascript
复制
re.findall( '(.+?):\s(.+?)\n', string, re.S), 

然而,我有一段时间抓住了所有与农民相关的价值观。

在每个值之后有一个换行符,当值是多行时,在值之前有一个选项卡或一系列制表符。

目标是拥有这样的东西:

代码语言:javascript
复制
{ 'apples': 20, 'farmers': ['elmer fudd', 'farmer ted'] }

等。

提前谢谢你的帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-15 23:37:44

下面是一个非常愚蠢的解析器,它考虑到了(明显的)缩进规则:

代码语言:javascript
复制
def parse(s):
    d = {}
    lastkey = None
    for fullline in s:
        line = fullline.strip()
        if not line:
            pass
        elif ':' not in line:
            indent = len(fullline) - len(fullline.lstrip())
            if lastindent is None:
                lastindent = indent
            if lastindent == indent:
                lastval.append(line)
        else:
            if lastkey:
                d[lastkey] = lastval
                lastkey = None
            if line.endswith(':'):
                lastkey, lastval, lastindent = key, [], None
            else:
                key, _, value = line.partition(':')
                d[key] = value.strip()
    if lastkey:
        d[lastkey] = lastval
        lastkey = None
    return d

import pprint
pprint(parse(string.splitlines()))

产出如下:

代码语言:javascript
复制
{'apples': '20',
 'oranges': '30',
 'ripe': ['elmer fudd', 'farmer ted', 'farmer bill'],
 'selling': ['carrots', 'potatoes']}

我认为这已经足够复杂了,作为一个显式的状态机,它看起来会更清晰,但是我想用任何新手都能理解的术语来编写它。

票数 1
EN

Stack Overflow用户

发布于 2013-10-15 22:46:43

您可能会看到PyYAML,这个文本非常接近,如果不是实际有效的YAML。

票数 2
EN

Stack Overflow用户

发布于 2013-10-15 23:16:15

以下是一种完全愚蠢的方法:

代码语言:javascript
复制
import collections


string = """
    apples: 20
    oranges: 30
    ripe: yes
    farmers:
            elmer fudd
                   lives in tv
            farmer ted
                   lives close
            farmer bill
                   lives far
    selling: yes
    veggies:
            carrots
            potatoes
    """


def funky_parse(inval):
    lines = inval.split("\n")
    items = collections.defaultdict(list)
    at_val = False
    key = ''
    val = ''
    last_indent = 0
    for j, line in enumerate(lines):
        indent = len(line) - len(line.lstrip())
        if j != 0 and at_val and indent > last_indent > 4:
            continue
        if j != 0 and ":" in line:
            if val:
                items[key].append(val.strip())
            at_val = False
            key = ''
        line = line.lstrip()
        for i, c in enumerate(line, 1):
            if at_val:
                val += c
            else:
                key += c
            if c == ':':
                at_val = True
            if i == len(line) and at_val and val:
                items[key].append(val.strip())
                val = ''
        last_indent = indent

    return items

print dict(funky_parse(string))

输出

代码语言:javascript
复制
{'farmers:': ['elmer fudd', 'farmer ted', 'farmer bill'], 'apples:': ['20'], 'veggies:': ['carrots', 'potatoes'], 'ripe:': ['yes'], 'oranges:': ['30'], 'selling:': ['yes']}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19392356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档