我正在查看一堆字符串,试图将某些字符串与以下模式进行匹配。
location_pattern = re.compile( r"""
\b
(?P<location>
([A-Z]\w*[ -]*)+[, ]+
(
[A-Z]{2}
|
[A-Z]\w+\ *\d ##
)
)
\b
""", flags=re.VERBOSE)
现在这个正则表达式几乎可以在我的所有数据集上运行,但这个特定字符串需要永远(好吧,5秒):
' JAVASCRIPT SOFTWARE ARCHITECT, SUCCESSFUL SERIAL'
在我的输入数据中的某个点上有一堆像这样的字符串(所有大写字母,大量的空格字符),并且程序在点击它时会大大减慢。我尝试取出正则表达式的不同部分,结果证明罪魁祸首是 注释行末尾的 \ * \ d 。
我想了解这是如何导致正则表达式验证花费这么长时间的。
有人可以帮忙吗?
答案 0 :(得分:1)
除了Greg的回答,你也有这种模式:
([A-Z]\w*[ -]*)+
^----^-^---- Note embedded quantifiers!
在重复组中使用量词(更糟糕的是2个量词)通常会产生灾难性的回溯问题。因此,我认为正则表达式。
评论:如果您稍后通过更新我的答案添加更多样本数据和预期输出,我可以为您提供另一个正则表达式。
答案 1 :(得分:1)
删除\ *\d
的原因之一是因为您只是将问题中的示例从不匹配的案例转换为匹配的案例。在回溯引擎中,匹配情况通常比非匹配情况花费的时间少得多,因为在非匹配情况下,引擎必须耗尽搜索空间才能得出结论。
问题所在的地方是联邦政府正确指出的(虽然解释是挥手而且不准确)。
([A-Z]\w*[ -]*)+
由于[ -]*
是可选的且\w
可以与[A-Z]
匹配,因此上面的正则表达式退化为([A-Z][A-Z]*)+
,这与灾难性回溯(A*)*
的典型示例相匹配。退化形式还表明问题出现在长字母大写的字符串上。
片段本身不会造成太大伤害。但是,只要续集(上面的片段之后的任何内容)失败,就会导致灾难性的回溯。
这是重写它的一种方法(不知道你的确切要求):
[A-Z]\w*(?:[ -]+[A-Z]\w*)*[ -]*
通过强制[ -]+
至少一次,模式不能再以多种方式匹配大写字母的字符串。