python - 匹配逗号分隔的键=值列表的正则表达式,其中值可以包含逗号

标签 python regex parsing python-2.6

我有一个天真的“解析器”,它只是做类似的事情:
[x.split('=') for x in mystring.split(',')]

但是 mystring 可以是这样的
'foo=bar,breakfast=spam,eggs'

显然,
天真的 split 者不会这样做。为此,我仅限于Python 2.6 标准库
所以例如 pyparsing不能使用。

预期输出为
[('foo', 'bar'), ('breakfast', 'spam,eggs')]

我正在尝试使用正则表达式执行此操作,但我面临以下问题:

我的第一次尝试
r'([a-z_]+)=(.+),?'
给我
[('foo', 'bar,breakfast=spam,eggs')]

显然,
使 .+ 非贪婪并不能解决问题。

所以,
我猜我必须以某种方式强制使用最后一个逗号(或 $)。
只是那样做是行不通的,
r'([a-z_]+)=(.+?)(?:,|$)'
与此一样,省略了包含 1 的值中逗号后面的内容,
例如[('foo', 'bar'), ('breakfast', 'spam')]

我想我必须使用某种后视(?)操作。
问题
1. 我使用哪个?或者
2. 如何我该怎么做?

编辑:

基于 daramarak下面的回答,
我最终做了与 abarnert 几乎相同的事情后来suggested以稍微冗长的形式;

vals = [x.rsplit(',', 1) for x in (data.split('='))]
ret = list()
while vals:
    value = vals.pop()[0]
    key = vals[-1].pop()
    ret.append((key, value))
    if len(vals[-1]) == 0:
        break

编辑 2:

为了满足我的好奇心,这真的可以用正则表达式吗?即 re.findall() 会返回一个二元组列表?

最佳答案

只是为了比较,下面是一个似乎也能解决问题的正则表达式:

([^=]+)    # key
=          # equals is how we tokenise the original string
([^=]+)    # value
(?:,|$)    # value terminator, either comma or end of string

这里的技巧是限制您在第二组中捕获的内容。 .+ 吞下了 = 符号,这是我们可以用来区分键和值的字符。完整的正则表达式不依赖于任何回溯(因此它应该与类似 re2 的东西兼容,如果需要的话)并且可以在 abarnert 的示例上工作。

用法如下:

re.findall(r'([^=]+)=([^=]+)(?:,|$)', 'foo=bar,breakfast=spam,eggs,blt=bacon,lettuce,tomato,spam=spam')

哪个返回:

[('foo', 'bar'), ('breakfast', 'spam,eggs'), ('blt', 'bacon,lettuce,tomato'), ('spam', 'spam')]

关于python - 匹配逗号分隔的键=值列表的正则表达式,其中值可以包含逗号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14641750/

相关文章:

python - Django:导入错误:没有名为 social.apps.django_app 的模块

python - 了解 json.loads() 中的 object_pairs_hook

.net - 将文本字符串解析为 F# 代码

Python Twitter 工具和 gzip 错误 "IOError: CRC check failed"

python - os.listdir() 给出的列表比预期的要大

regex - 可以在 Vim 中组合多个突出显示组吗?

java - 在java中为字符串写一个正则表达式

javascript - JS正则表达式仅替换重复 block 的第一个 block 中的内容

Python:如何优化这个 CSV 解析循环?

python - 字典中的 "TypeError: ' unicode ' object does not support item assignment"