我有一个天真的“解析器”,它只是做类似的事情:
[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/