这一行代码(我相信)寻找一个以foo开头,以bar结尾的子字符串,其中包含任何内容,包括换行,并从字符串中删除它。
zip = string.replace(/foo(.|\s)*bar/, '');出于某种原因,当我把一个非常大的字符串穿过这个,有很大一部分不是在foo和bar之间,它就会崩溃Chrome。Chrome不显示任何错误信息,控制台也不显示错误消息,但是选项卡会冻结,并拒绝执行任何操作,只会关闭。
由于外部的内容相对较少,这不会崩溃,而在foo和bar中有大量内容时,它不会崩溃。这并不是因为字符串太大,JS对它的字符串没有限制,其他.replace函数也使用相同大小的字符串。会不会是写得不好的regex之类的?
发布于 2013-12-26 02:06:21
浏览器与regex /foo(.|\s)*bar/崩溃,但不像pete所建议的/foo[\s\S]*bar/崩溃,原因是回溯地狱。
一个(未优化的) NFA正则表达式引擎将尝试第一个分支,如果匹配失败,它将返回到第二个分支。一个更好的引擎可以分析语法,并将.和\s合并到一个字符类中,这样就不会浪费时间回溯。
让我们考虑一下这一投入:
foo notba other对于regex /foo(.|\s)*bar/,由于空格(ASCII 32)可以同时匹配.和\s,在.分支匹配失败后,它将尝试\s分支:
foo notba other
^^^^^^^^^^^ ^^^^^空格字符数是regex引擎所探索的二叉树的级别数。如果字符串包含foo但不包含bar,则时间复杂度将以指数方式增加空格字符的数量。
考虑到pete的修改/foo[\s\S]*bar/,没有分支,因为所有东西都已经由字符类检查过了,所以当我们在失败时回溯时,我们没有任何未开发的分支,并且会很快返回失败。
发布于 2013-12-26 01:54:51
语法(.|\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建议的“回溯地狱”。
https://stackoverflow.com/questions/20778196
复制相似问题