为什么此代码会导致Chrome窒息?

时间:2013-08-01 15:43:59

标签: javascript regex google-chrome

我正在尝试调试我的应用中的问题,我已经缩小到涉及正常表达式的特定情况,导致Chrome窒息!在Firefox中尝试相同的代码可以正常工作。如果我减少我的样本'运行正则表达式的文本也可以。

那是什么给了什么?

以下是jsfiddle:http://jsfiddle.net/XWKRb/1/ (这将无法初始化,因为如果你得到与我相同的结果,Chrome会窒息)

我在jsfiddle中输入的代码是:

var rgx = /^(\d+([,|;]?\d*))*$/;
var sample = '40162690,40162755,40162691,40168355,40168357,40162726,40162752,40162729,40428707 ,40162740,40162546';
alert("Test is "+rgx.test(sample));

也许有更好的方法来编写我的正则表达式来避免这个问题?目标是正则表达式应该捕获一串用逗号或分号分隔的数字。

2 个答案:

答案 0 :(得分:13)

您有catastrophic backtracking的经典案例:

^(\d+([,|;]?\d*))*$
    ^      ^  ^  ^
    |      |  |  ---- zero or more repetitions of the group 
    |      |  ------- zero or more digits
    |      ---------- zero or one comma, pipe or semicolon
    ----------------- one or more digits

包含一个包含可选元素的重复组,其中一个元素会自行重复。暂时忽略分隔符,你基本上有正则表达式

^(\d+\d*)*$

这导致你的正则表达式在最坏的情况下必须检查的指数数量的排列。

只要在你的字符串中找到了允许字符之外的另一个字符(就像你的例子中的空格一样),正则表达式必须失败 - 但需要引擎年龄来计算出来。有些浏览器会检测到这种失控的正则表达式匹配,但Chrome似乎想要解决此问题。

为了说明这一点,在RegexBuddy中测试正则表达式会显示以下内容:

Input             Steps to determine a non-match
1,1X                   23
12,21X                119
123,321X              723
1234,4321X          4,743
12345,54321X       31,991
123456,654321X    217,995
1234567,7654321X  attempt aborted after 1,000,000 steps

答案 1 :(得分:4)

这种模式会更好用:

var rgx = /^\d+(?:[,;]\s*\d+)*$/;