【问题标题】:re.search() hungre.search() 挂起
【发布时间】:2018-09-27 06:35:40
【问题描述】:

此代码 sn-p 旨在在提供的文件的每一行上搜索正则表达式匹配。 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

【问题讨论】:

  • sample.txt 有多大?
  • 您要匹配的实际数据是什么?您的正则表达式模式与示例数据完全不匹配。
  • 添加了我要匹配的示例数据。文件大小为 3.84 MB,与问题提供的数据完全相同。
  • 运行完全发布的代码会产生挂起吗?
  • 是的,它提供以下输出,然后挂起:“开始...”。如果我们删除包含 "#"s 的行,我们会得到预期的输出。

标签: python regex python-2.7


【解决方案1】:

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

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

【讨论】:

  • 好吧,那没有得到那么多选票...我不明白,因为这是一个很好的正则表达式问题,有正确答案:)
【解决方案2】:

正则表达式引擎可以达到很高的复杂性,特别是当它必须回溯时,就像你的情况一样。

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

2016 年 7 月 20 日,我们从 UTC 时间 14:44 开始经历了 34 分钟的中断。花了 10 分钟找出原因,14 分钟编写代码来修复它,10 分钟将修复推出到 Stack Overflow 再次可用的地步。

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

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

我会提出一个解决方法,因为您在这里并不需要正则表达式,使用 str.split 会做而且速度很快,因为它只搜索子字符串(O(N) 方法)然后创建 2 个字符串,这是等效的你想用正则表达式做什么:

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

结果

foo bar

【讨论】:

    猜你喜欢
    • 2019-02-23
    • 1970-01-01
    • 2013-09-02
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 2015-07-06
    • 2011-03-07
    相关资源
    最近更新 更多