如何优化Python正则表达式的性能?
简介
Python中有一个名为re 的特定于正则表达式的内置库。你只需要导入它就可以使用它的功能(例如search、match、findall等)。它们会为你返回一个Match对象,其中包含修改结果的有用技术。
根据维基百科,正则表达式(也称为regexp)是指定搜索模式的字符集合。它是一个工具,使你能够过滤、提取或修改一系列字符。人们还发现,当使用“in”运算符时,正则表达式的运行速度更快。
正则表达式存在性能问题,通常难以调试和维护。为了提高它们的性能,必须解决这些问题。
示例
import re my_string = 'I like tortilla.' # 'like (\w+)' is a regexp that matches 'like' followed by a space followed by # any number of word characters ('\w' means 'word character' and '+' means '1 or more'), # putting those word characters in a capture group (the parenthesis) regex_result = re.search(r'like (\w+)', my_string) print(regex_result.groups())
输出
('tortilla',)
Soundex函数首先检查输入是否为非空的字母字符串。最好的方法是什么?
如果你回答“正则表达式”,那就去角落里坐一会儿,反思一下你糟糕的直觉。正则表达式很少是正确的答案;应该尽可能避免使用它们。不仅是因为性能原因,还因为它们难以调试和维护。同样,也因为性能原因。
这段来自soundex/stage1/soundex1a.py的代码片段检查函数参数source是否完全由字母组成的单词,并且至少包含一个字母(不是空字符串)−
为什么正则表达式的效率很重要?
设计糟糕的正则表达式可能需要很长时间才能执行,并严重降低系统速度,即使精心设计的正则表达式可能非常有效。BMC Discovery已经过多次升级,使其比早期版本更能抵抗无效的正则表达式。
当应用于中等大小的字符串时,设计一个需要花费数小时、数天甚至整个宇宙寿命才能完成的正则表达式是完全可能的。此外,它在多个处理器之间分配执行TPL模式的工作,以便即使一个处理器忙于冗长的正则表达式匹配,其他处理器也可以继续工作。
低效正则表达式的构成
那么,如何创建一个低效的常用短语呢?一个问题是当正则表达式回溯太远时;如果正则表达式有几个重复运算符,就会发生这种情况。+、*或n、m是重复运算符的示例。如果正则表达式进行了部分匹配但在之后失败,则它必须循环返回并尝试任何其他可能的局部匹配,以防其中任何一个成功。
例如,考虑使用正则表达式a.*b.*cd匹配字符串abc abc abc。由于字符串中没有d,因此匹配将永远不会成功。但是,在放弃之前,正则表达式仍然必须穷尽字母组合a、b和c的所有可能性。
"*abc* abc abc", "*ab*c ab*c* abc", "*ab*c abc ab*c*", "*a*bc a*bc* abc", "*a*bc a*b*c ab*c*", "*a*bc abc a*bc*", "abc *abc* abc", "abc *ab*c ab*c*", "abc *a*bc a*bc*", "abc abc *abc*"
作为一个粗略的指南,正则表达式需要执行的比较次数与字符串的长度乘以可能的中间匹配数成正比。
在这个例子中,使用非贪婪运算符,即a.*?b.*?cd,对它将进行的匹配次数没有影响,因为正则表达式引擎仍然需要尝试每种组合。
编写高效正则表达式的指南
考虑潜在的失败情况
正如前面的例子所示,当正则表达式完全不匹配,但存在多个部分匹配时,问题就出现了。编写正则表达式时,务必考虑正则表达式在失败时的运行方式以及成功时的运行方式。
尝试快速失败
如果正则表达式到达无法匹配所需目标的点,请尝试使整个正则表达式失败。
分析——特别是失败的案例
为了确保你的正则表达式匹配你预期的内容,验证它是至关重要的。但是,对仅部分匹配它的长字符串(例如兆字节长的随机字母字符串)评估正则表达式的效率也很重要。
除非必要,否则不要使用分组
当你使用括号括起正则表达式的一部分时,正则表达式引擎必须更努力地保存由该组匹配的文本,以防以后需要它。这可能会减慢匹配过程,有时会降低四倍或更多。
如果需要使用括号但不需使用组的内容,例如当正则表达式的一部分重复时,可以使用括号的非分组变体(?:)。
结论
有些人可能会反驳说,对于这类操作,Pandas更好。但是,我不认为它会像我们构建的纯Python版本那样快,因为它需要更长的时间才能将数据集加载到DataFrame中。
其他选项,例如使用regex库或将数据分成多个部分并并行计数(一种与map-reduce相关的策略,这是大数据中非常相关的算法),可以进一步提高速度。
数据结构
网络
关系数据库管理系统(RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP