re模块中的贪婪和贪婪

时间:2015-04-13 14:44:12

标签: python regex greedy

re模块中/(a +)+ c /和/(a +)c /之间有什么区别? 我检查了执行需要多长时间。 有很大的不同。 我想知道为什么会有很大的不同。 我把这个样本输入到在线正则表达式测试器的形式,但我不明白发生了什么。 请用语言告诉我。

import re
from time import clock    
def test(f, *args, *kargs):
  start = now()
  f(*args, *kargs)
  print("The function %s lasted: %f" % (f.__name__, now() - start))

def catastrophic1(n):
  print("Testing with %d characters" % n)
  pat = re.compile("(a+)+c")
  text = "%s" % 'a' * n
  pat.search(text)

def catastrophic2(n):
  print("Testing with %d characters" % n)
  pat = re.compile("(a+)c")
  text = "%s" % 'a' * n
  pat.search(text)

for n in range(13, 20):
  test(catastrophic1, n)
for n in range(13, 20):
  test(catastrophic2, n)

2 个答案:

答案 0 :(得分:1)

两个表达式都匹配相同的内容,即一个或多个a s后跟一个c

表达式(a+)+c对正则表达式引擎进行处理更耗时,因为此表达式可以通过更多方式匹配a字符串。

例如,使用第二个表达式,字符串aaaaaa可以分解为以下组

(a)(a)(a)(a)(a)(a) # here (a+) matches a single 'a'
(aa)(aa)           # here (a+) matches 'aa'
(aaa)(aaa)         # here (a+) matches 'aaa'

答案 1 :(得分:1)

这个问题的答案取决于你能够理解python正则表达式引擎如何解释+以及它如何匹配模式。

实际上,python正则表达式引擎使用Traditional NFA进行正则表达式匹配,并基于NFA引擎的本质:

  

它依次考虑每个子表达式或组件,每当需要在两个同样可行的选项之间做出决定时,它会选择一个并记住另一个,如果需要则返回到以后。它必须在行动方案中决定的情况包括具有量词的任何事物(决定是否尝试另一场比赛)和交替(决定哪个改变本地尝试,以及哪个稍后离开)。无论尝试哪种行为,如果它成功并且正则表达式的其余部分也成功,则匹配结束。如果正则表达式的其余部分中的任何内容最终导致失败,则正则表达式引擎知道它可以回溯到它选择第一个选项的位置,并且可以通过尝试其他选项继续匹配。这样,它最终会尝试正则表达式的所有可能排列(或至少在找到匹配项之前所需的数量)。*

除了+正则表达式引擎的上述过程之外,还将尝试从长度为1或更长的前一个模式的所有组合,因此对于像(a+)+c这样的模式,我们有一个指数的尝试次数!它会吞噬很多时间!


<子> *掌握正则表达式,第三版,作者:Jeffrey E. F. Friedl!