如何解决正则表达式花费太多时间
我创建了2个正则表达式(re1和re2),如果我尝试编译第一个正则表达式(re1),则大约需要30秒才能找到所有匹配项。 如果我尝试编译第二个正则表达式(re2),则大约需要1秒钟才能找到所有匹配项。
您能帮我找出差异或造成此问题的原因吗? 谢谢!
import re
data = b'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
re1 = b'.*00.*00.*00.*00.*76.*62.*55.*75.*'
re2 = b'.*aa.*00.*00.*6f.*63.*20.*6d.*75.*'
reg = re.compile(b'^%s$' % re1,re.RegexFlag.M)
results = len(reg.findall(data))
print(results)
解决方法
问题来自CPython正则表达式引擎的实现中的回溯(由@Thefourthbird强调)。它更具体地来自第一个.*
和最后一个findall
,如果数据不包含换行符,则不需要 。实际上,在这种情况下,.*
只会找到一个匹配项(由于findall
而导致的所有数据),或者什么也找不到。因此,您不需要search
:^
就足够了。此外,使用$
和.*
加上前缀和后缀import re
data = b'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
re1 = b'00.*00.*00.*00.*76.*62.*55.*75'
re2 = b'aa.*00.*00.*6f.*63.*20.*6d.*75'
reg = re.compile(re1,re.RegexFlag.M)
results = 1 if reg.search(data) else 0
print(results)
也没有用。下面的代码应该产生相同的效果,但是在我的机器上要快20倍(就输入大小而言,还不是很快)。
.
如果数据包含换行符,则将更加复杂,因为只有包含模式的行将被匹配。实际上, RegexFlag.DOTALL
与换行符不匹配(因为search
不存在)。解决该问题的一种方法是先分割行,然后再应用正则表达式。另一种解决方案是使用上面的代码,然后用finditer
替换re1
行以跟踪匹配项的位置,然后跟踪每个匹配项的行的开头和结尾。
如果您想进一步了解回溯为什么会导致执行速度如此缓慢,请查看这篇文章:Why can regular expressions have an exponential running time?。
请注意, Max TemperatureC Min TemperatureC Mean TemperatureC
CET
1997-01-01 7.0 2.0 4.0
1997-01-02 7.0 0.0 3.0
1997-01-03 5.0 2.0 3.0
1997-01-04 7.0 -1.0 3.0
1997-01-05 2.0 -1.0 0.0
对于此数据而言是非常关键的正则表达式。有更快的正则表达式引擎来计算它。 Google的RE2 正则表达式引擎是一个线性时间正则表达式引擎,在这种紧急情况下(但非关键数据通常不会如此),它的速度应该更快。还有 Intel的Hyperscan 正则表达式引擎,与其他引擎相比,它的运行速度通常非常快(尽管用户友好程度有所降低)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。