当前位置: 首页 > 面试题库 >

正则表达式以匹配逗号分隔的key = value列表,其中value可以包含逗号

缪风史
2023-03-14
问题内容

我有一个幼稚的“解析器”,它只做以下事情:
[x.split('=') for x in mystring.split(',')]

但是mystring可以像
'foo=bar,breakfast=spam,eggs'

显然,
天真的拆分器不会这样做。为此,我仅限于 python 2.6标准库
因此无法使用pyparsing。

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

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

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

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

因此,
我猜测我必须以某种方式使最后一个逗号(或$)成为必需。
这样做实际上是行不通的,
r'([a-z_]+)=(.+?)(?:,|$)'
因为省略了逗号后面包含一个值的内容,
例如[('foo', 'bar'), ('breakfast', 'spam')]

我认为我必须使用某种look-behind(?)操作。
问题
1.我要使用 哪一个 ?或
2. 该怎么做?

编辑

根据下面的daramarak的回答,
我最终做了一些与abarnert稍后提出的建议大致相同的事情;

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()将返回2元组的列表?


问题答案:

仅出于比较目的,这是一个正则表达式似乎也可以解决该问题:

([^=]+)    # 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')]


 类似资料:
  • 我需要一个. Net(C#)正则表达式来匹配逗号分隔的数字列表,如果有逗号作为最后一个字符,这些数字将不匹配 我已经找到了这个Regex但是当结尾有逗号时匹配 什么是符合这种模式的正则表达式模式? 编辑:为清晰起见添加了1个示例,正确答案适用于

  • 问题内容: 在我的一个项目中,我不得不处理逗号分隔文件(CSV)。我必须基于逗号来拆分数据,而忽略引号内的逗号(即),因此我使用了另一个堆栈溢出问题(Java:拆分逗号分隔的字符串但忽略了引号中的逗号)中提到的表达式。一切工作都很好,直到最近我才注意到它不适用于下面提到的一种特定情况。 我需要在逗号上拆分的数据字符串为: 以我的理解为基础 拆分后的数据应返回一个大小为10的数组,该数组的后两个索引

  • 我在Javascript中有以下正则表达式: 这将检查字符串是否至少有两个大于1个字符的单词。 前- 我现在有了一个新的要求,我试图实现它,但不能正确执行。 新要求:能够有一个逗号分隔的相同类型的输入列表。不能以逗号结尾。根据上述规则,每个项目必须有效 如果没有逗号,则其也是有效的 所有字符都是字母,没有数字/特殊字符

  • 问题内容: 我的文字如下: 谁能告诉我我必须使用哪些正则表达式分度数才能获得以下结果: 我在这里阅读Sun教程,直到“ Matcher类的方法”为止,但我仍然茫然。谢谢! 如果是这样,那将很容易,但是不幸的是,事实并非如此。有任何想法吗? 问题答案: 您可以直接使用split()方法,如下所示: (请注意,这将返回长度为5的数组,第一个位置为空字符串) 或者,如果您想使用模式/匹配器,可以这样做:

  • 我使用以下正则表达式来验证单个电子邮件地址。如何使此正则表达式接受以逗号分隔的电子邮件地址列表? 我使用razor视图将正则表达式放置在输入标记中:

  • 问题内容: 我需要运行类似的查询: 但是我希望子选择返回逗号分隔的列表,而不是数据列。这有可能吗?如果可以,怎么办? 问题答案: 您可以使用GROUP_CONCAT执行该操作,例如