为什么python的re.search方法会挂起?

时间:2017-04-09 18:59:39

标签: python regex

我使用python正则表达式库解析一些字符串,目前我发现我的正则表达式太复杂或者我搜索的字符串太长。

以下是挂断的示例:

>>> import re
>>> reg = "(\w+'?\s*)+[-|~]\s*((\d+\.?\d+\$?)|(\$?\d+\.?\d+))"
>>> re.search(reg, "**LOOKING FOR PAYPAL OFFERS ON THESE PAINTED UNCOMMONS**") #Hangs here...

我不确定发生了什么。任何帮助表示赞赏!

编辑:以下是我尝试匹配的示例的链接:Regxr

1 个答案:

答案 0 :(得分:4)

代码执行挂起的原因是catastrophic backtracking,因为在量化组(\w+'?\s*)+内允许正则表达式引擎测试的一个强制性和1个以上可选模式(可以匹配空字符串的模式)很多匹配的路径,很多都需要很长时间才能完成。

我建议以'\s成为强制性的方式展开有问题的群体,并将其包装在可选群组中:

(\w+(?:['\s]+\w+)*)\s*[-~]\s*(\$?\d+(?:\.\d+)?\$?)
^^^^^^^^^^^^^^^^^^^***

请参阅regex demo

在这里,(\w+(?:['\s]+\w+)*)将匹配1个以上的字符,然后是0 + 1 + '或空格的序列,后跟1个字的字符。这样,如果出现不匹配的字符串,则模式将变为线性,并且正则表达式引擎会更快地使匹配失败。

其余模式:

  • \s*[-~]\s* - 包含0 +空格的-~
  • (\$?\d+(?:\.\d+)?\$?) - 第2组捕获
    • \$? - 1或0 $个符号
    • \d+ - 1+位数
    • (?:\.\d+)? - 1或0个零序列:
      • \. - 一个点
      • \d+ - 1+位数
    • \$? - 1或0 $个符号