Jquery .replace崩溃浏览器

时间:2013-12-26 01:31:58

标签: javascript jquery regex string replace

这行代码(我相信)查找以foo开头并以bar结尾的子字符串,其中包含任何内容,包括换行符,并将其从字符串中删除。

zip = string.replace(/foo(.|\s)*bar/, '');

出于某种原因,当我在其中放入一个非常大的字符串时,大部分字符串不在foo和bar之间,它会导致Chrome崩溃。 Chrome不会显示任何错误消息,控制台也没有,但是标签会冻结,并且拒绝执行任何操作,只能关闭。

外部内容相对较小,这不会崩溃,并且foo和bar内部有大量内容,它不会崩溃。这不是因为字符串太大,JS对它的字符串没有限制,而其他.replace函数使用相同大小的字符串。它可能是一个写得不好的正则表达式吗?

2 个答案:

答案 0 :(得分:3)

浏览器与正则表达式/foo(.|\s)*bar/崩溃,而不是因为回溯地狱而由pete建议的/foo[\s\S]*bar/

(未经优化的)NFA正则表达式引擎将尝试第一个分支,如果匹配失败,它将回溯到第二个分支。一个更好的引擎可以分析语法,并将.\s组合成一个字符类,这样就不会浪费时间回溯。

让我们考虑一下这个输入:

foo           notba     other

对于正则表达式/foo(.|\s)*bar/,由于空格(ASCII 32)可以匹配.\s,因此.分支的匹配失败后,它将尝试{ {1}}分支:

\s

空格字符数是正则表达式引擎探索的二叉树的级别数。如果字符串包含foo notba other ^^^^^^^^^^^ ^^^^^ 但不包含foo,则时间复杂度会以空白字符数呈指数级增长。

考虑pete的修改bar,没有分支,因为一切都已被字符类检查过,所以当我们回溯失败时,我们没有任何未经探索的分支,并且会很快返回失败。

答案 1 :(得分:2)

语法(.|\s)*有点奇怪。

它基本上是(capture anything but a new line OR capture whitespace){as many times as needed},但是JavaScript再没有一种模式。匹配换行符。

请尝试使用/foo([\s\S]*)bar/[\s\S]字符类匹配一个字符,该字符是空白字符(包括换行符)或不是空白字符的字符。由于所有字符都是空格或非空格,因此该字符类匹配任何字符。见http://www.regular-expressions.info/dot.html

崩溃的原因很可能是nhahtdh建议的“回溯地狱”