执行以下代码,需要永远:
"Hello there, very best wishes, from Syria...".match(/^((?:, |[\w ]+)+)$/)
在执行以下操作时,比以往任何时候都要少一点,但是超过十秒钟!
"Hello there, best wishes, from Syria...".match(/^((?:, |[\w ]+)+)$/)
...然后返回null
试用我的Ubuntu 12.04 64位计算机,Archlinux 32位服务器和Debian Wheezy 32位服务器,所有服务器都运行节点v0.10.18。
编辑:显然行为是从V8继承的,相同的代码会让Chrome的控制台挂起,而mongo shell(也使用V8)也会挂起!
答案 0 :(得分:1)
这个正则表达式是等价的并且运行得很快:
/^([\w, ]+)$/
问题在于你的正则表达式,而不是V8。其他引擎在尝试一段时间之后只报告不匹配(这不一定是正确的结果),V8尝试获得正确的结果,即使它需要永远。你需要注意你如何编写正则表达式,它就像任何其他代码一样 - 它不会神奇地防止程序员的错误。
答案 1 :(得分:1)
我很确定这里发生的事情是catastrophic backtracking。例如在我的机器上:
Hello there, best wishes, from Syria...
”中的39个字符,大约需要13-14秒。Hello there, vbest wishes, from Syria...
”中的40个字符,需要27-28秒。Hello there, vebest wishes, from Syria...
”中的41个字符,需要56秒。您可以看到所花费的时间呈指数级增长。为了解释正则表达式引擎如何通过回溯来匹配字符串,我将引用上面链接中的示例。它在字符串(x+x+)+y
上应用正则表达式xxxxxxxxxxy
:
让我们看看将此正则表达式应用于xxxxxxxxxxy时会发生什么。该 第一个x +将匹配所有10个x字符。第二个x +失败了。该 先x +然后回溯到9场比赛,第二场比赛拿到了 剩下的x。该组现已匹配一次。该组重复,但 在第一个x +失败。由于一次重复就足够了,小组 火柴。 y匹配y并找到整体匹配。正则表达式是 声明功能,代码发送给客户,他的 电脑爆炸。几乎。
当主题中缺少y时,上述正则表达式变得难看 串。当y失败时,正则表达式引擎会回溯。该小组有一个 迭代它可以回溯到。第二个x +只匹配一个x,所以 它不能回溯。但是第一个x +可以放弃一个x。第二个x + 及时匹配xx。该组再次进行一次迭代,下一次失败 一个,而y失败了。再次回溯,第二个x +现在有一个 回溯位置,减少自身以匹配x。小组尝试了 第二次迭代。第一个x +匹配,但第二个卡在 字符串的结尾。再次回溯,小组中的第一个x + 第一次迭代将自身减少到7个字符。第二个x +匹配 XXX。如果失败,则第二个x +减少到xx,然后减少到x。现在 group可以匹配第二次迭代,每个x +只有一个x。但是这个 (7,1),(1,1)组合也失败了。所以它转到(6,4)然后 (6,2)(1,1)然后(6,1),(2,1)然后(6,1),(1,2)然后我认为 你开始得到漂移。
请参阅杰夫关于正则表达式性能的this页面,该页面使用相同的示例。所以道德故事:不要只匹配东西,改善正则表达式。嵌套重复运算符时,请确保只有一种方法可以匹配相同的匹配。对于我引用xx+y
的示例,效果更好。对于你的正则表达式,Esailija给出的答案会更好/^([\w, ]+)$/