为什么这个正则表达式需要花费很多时间?^([a-zA-Z] + [0-9] [ - ] [^ \ s ._ ^%$#!〜@,])+ $

时间:2015-01-15 08:42:22

标签: ruby-on-rails ruby regex

这个正则表达式需要很多时间来匹配任何字符串。

匹配cbdvhuvffviuhwrevfnvfduvildouqjiofeqfelvimpupvcuipvhfjdvufhvfd,ofvhfuhffduisfdwfewdsiu

的字符串
^([a-zA-Z]+[0-9]*[-]*[^\s._^%$#!~@,])+$

Rubular停止工作。

1 个答案:

答案 0 :(得分:1)

  

正则表达式可能非常昂贵。某些(非预期的和预期的)字符串可能会导致RegExes表现出指数行为。

     

- (来自CodingHorror

当您有两个嵌套的变量匹配组时,可能会出现所谓的catastrophic backtracking,这些匹配组可以匹配正则表达式中的相同内容。

特别是如果inout与正则表达式不匹配,引擎将检查嵌套循环中组的所有组合,这可能需要相当长的时间。

基本上,正则表达式引擎总是会尝试匹配尽可能多的每个步骤的字符,即使是变量组(即具有+*?的序列。如果在某些时候,它达到这样的情况:输入字符串结束而没有正则表达式完全匹配,或者出现没有更多字符可以匹配当前组的情况,引擎将回溯。这意味着,它将“无法匹配”#34;一个角色,并尝试找到只有下一个变量组匹配的解决方案。

现在,在正则表达式中,您有一个嵌套的变量组。在这种情况下,引擎可能会遇到深度嵌套的循环,试图找到匹配的组合。这可能需要很长时间,因此有时可以用作DoS向量。

正则表达式引擎不是很聪明,并且可以通过非常简单的规则工作(请参阅维基百科上的Regular Language)。因此,他们通常不会自己检测这些循环,并会愉快地工作,尝试所有组合。

  

解决方案很简单。当嵌套重复运算符时,绝对确保只有一种方法可以匹配相同的匹配。如果重复内循环4次而外循环7次导致与重复内部相同的整体匹配循环6次,外循环2次,你可以确定正则表达式引擎会尝试所有这些组合。