re.search()挂起

时间:2018-09-27 06:35:41

标签: python regex python-2.7

此代码段旨在在提供的文件的每一行上搜索正则表达式匹配项。 re.search()挂在文件中包含“#”字符的行中3e + 5次。


该问题的解决方案是什么?

import re
print "Started..."
exp = "(.*)\$\$\$Uniqueterm:(.*)"
with open("sample.txt", 'r') as file:
    for line in file: 
        if re.search(exp, line):
            print "Found match: " + re.search(exp,line).groups()[1].strip()
    print "File finished..."

样本输入文件(sample.txt):

abc
pqr 
##### (3e+5 times '#' in a single line)
xyz
$$$Uniqueterm: Match it
qaz

预期输出:

Match it

2 个答案:

答案 0 :(得分:1)

您正在将re.search与以(.*)开头的正则表达式一起使用。 re.search在任何起始位置寻找匹配项,这意味着它必须从每个可能的起始索引处开始搜索,直到找到匹配项或用尽位置进行搜索为止。前导(.*)强制从搜索开始位置开始扫描整个字符串,以搜索每个开始位置

这是经典的灾难性回溯,只是部分回溯隐含在re.search的使用中,而不是内置在正则表达式中。您可以调整正则表达式以消除灾难性的回溯,但是为什么要使用正则表达式呢? str.splitstr.find之类的基本方法可以很好地完成工作。 Jean-FrançoisFabre的答案显示了一种实现方法。

答案 1 :(得分:0)

regex引擎可以达到很高的复杂度,尤其是在必须回溯的情况下(例如您的情况)。

因此,如果要搜索的表达式很长,并且您必须通过大量的反复试验(即回溯)来计算组,则搜索可能会花费很多时间(请参见a famous example of regex failure on StackOverflow network)。

  

2016年7月20日,我们从世界标准时间14:44开始经历了34分钟的停机。花了10分钟才能确定原因,花14分钟编写代码来解决该问题,并花10分钟将修复程序推广到Stack Overflow再次可用的地步。

     

直接原因是格式错误的帖子,导致我们的一个正则表达式消耗了Web服务器上的高CPU。该帖子位于主页列表中,这导致在每个主页视图上调用昂贵的正则表达式。   ...

     

此正则表达式已被子字符串函数替换。

我建议一种解决方法,因为您在这里实际上不需要正则表达式,使用str.split可以并且非常快捷,因为它只搜索子字符串(O(N)方法)然后创建2个字符串,相当于您要对正则表达式尝试执行的操作:

a = "foo$$$Uniqueterm:bar"
g1,g2 = a.split("$$$Uniqueterm:")
print(g1,g2)

结果

foo bar