【问题标题】:"Broken" regular expression?“破碎”的正则表达式?
【发布时间】:2013-06-12 08:25:36
【问题描述】:

我有用于解析许多值的正则表达式,例如a=b c=d e=f,这应该会导致像这样的字典:{'a': 'b', 'c':'d', 'e':'f'}。我希望用户允许使用 \ 转义值,因此我使用了 ((?:[^\\\s=]+|\\.)+) 并添加了 (?:^|\s)(?=\s|$),而不是真正简单的正则表达式,因此表达式不会匹配部分结果。

>>> import re
>>> reg = re.compile(r'(?:^|\s)([\w\d]+)=((?:[^\\\s=]+|\\.)+)(?=\s|$)')
>>> s = r'a=b c=d e=one\two\three'
>>> reg.findall(s)
[('a', 'b'), ('c', 'd'), ('e', 'one\\two\\three')]

但后来有人过来并将=插入到事物的右侧。

>>> s = r'a=b c=d e=aaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbb\cccc
    ccccc=dddddddddddddddd\eeeeeeeeeeeeeee'    
>>> reg.findall(s)

脚本卡在这一行(我已经等了几个小时,但没有完成)。

问题:这是不是很糟糕的正则表达式(为什么?你会怎么写?)还是正则表达式的实现错误?

注意:我不是在为这个问题寻求解决方案,我很好奇为什么 findall() 没有在几个小时内完成。

【问题讨论】:

  • 为什么不让=出现在=的右边,而你的分隔符是空格?
  • @DavidFoerster 这是一个错误(已经修复)。我很感兴趣为什么findall 永远不会结束。
  • 真正的问题是“为什么你有这么糟糕的格式”?使用 JSON、YAML、换行符分隔的 key=value 对等等!
  • @kirelagin 第三方应用程序。对此无能为力。

标签: python regex python-3.2


【解决方案1】:

您的问题是您嵌套重复,并且重新引擎似乎尝试了它们之间的所有可能分布:

r'(?:^|\s)([\w\d]+)=((?:[^\\\s=]+|\\.)+)(?=\s|$)'
                                ^     ^

更好:

r'(?:^|\s)([\w\d]+)=((?:[^\\\s=]|\\.)+)(?=\s|$)'

实际上 findall 会完成(或内存不足)。你可以试试这个

s = r'a=b c=d e=aaaaaaa\bbbbbbbb\ccccccccc=ddddddddd\eeeee'

然后在“e=”后面依次添加字符

【讨论】:

  • 很好奇。我期待正则表达式能够处理这样的情况。
  • @Vyktor 比你绝对应该阅读名为“掌握正则表达式”的书。太棒了。
【解决方案2】:

除了非常简单的情况外,正则表达式不是适合您的任务的工具。您需要对输入字符串进行标记。

在简单的情况下你可以使用str.split():

for tok in s.split(" "):
    tok = tok.split("=", 1)
    key = tok[0]
    value = tok[1]

我已经很久没有写过python了,所以我不确定for … in …的说法是否正确,但你明白我的意思。

【讨论】:

  • 在这种情况下不使用正则表达式是完全正确的,但您的解决方案没有转义。
  • 不,可以有\ (转义空间),因此我不能使用标记化。或者至少不是这个简单的实现。
  • 我知道,我的示例不允许转义——因此“在简单的情况下”。这只是为了说明我的想法。
【解决方案3】:
>>> import re
>>> reg = re.compile(r'(\w+)=(\S+)')
>>> dict(reg.findall(r'a=b c=d e=one\two\three'))
{'e': 'one\\two\\three', 'a': 'b', 'c': 'd'}
>>> dict(reg.findall(r'a=b c=d e=aaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbb\ccccccccc=dddddddddddddddd\eeeeeeeeeeeeeee'))
{'e': 'aaaaaaaaaaaaaaaaaaaaaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbb\\ccccccccc=dddddddddddddddd\\eeeeeeeeeeeeeee', 'a': 'b', 'c': 'd'}

【讨论】:

    猜你喜欢
    • 2016-08-31
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多