【问题标题】:Why does /^(.+)+Q$/.test("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") take so long?为什么 /^(.+)+Q$/.test("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") 需要这么长时间?
【发布时间】:2012-04-19 09:14:21
【问题描述】:

当我跑步时

/^(.+)+Q$/.test("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")

在 Chrome 或 IE 中,大约需要 10 秒才能完成。 (Firefox 几乎可以立即对其进行评估。)

为什么需要这么长时间? (以及 Firefox 为何/如何能够如此迅速地做到这一点?)

(当然,我永远不会运行这个特定的正则表达式,但我在http://daringfireball.net/2010/07/improved_regex_for_matching_urls 遇到了与 URL 正则表达式类似的问题,它似乎归结为这一点,即某些 URL 会导致浏览器锁定)

例如:

var re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i;
re.test("http://google.com/?q=(AAAAAAAAAAAAAAAAAAAAAAAAAAAAA")

【问题讨论】:

  • 一个原因可能是它做了很多回溯。这并不能解释为什么 Firefox 更快。也许他们有一些额外的优化。如果您想了解更多关于正则表达式引擎的内部工作原理,我建议您阅读shop.oreilly.com/product/9780596528126.do
  • @thg 将此作为答案发布,请
  • 任何在(x+x+)+y 上命中“灾难性回溯”的正则表达式引擎根本不值得一提。该正则表达式不需要任何回溯。如果通过 NFA 模拟器实现,而不是作为 DFA 实现,则不会。
  • 这是一种求知欲的练习吗?如果不是,请解释您为什么使用该正则表达式,因为它看起来很可怕,因为/.+Q$/ 可以正常工作,甚至可能只是/Q$/

标签: javascript regex webkit


【解决方案1】:

正如 thg435 所指出的,这听起来像是灾难性的回溯。有一篇很棒的文章,Regular Expression Matching Can Be Simple And Fast

它描述了一种称为 Thompson NFA 的有效方法。但是,如上所述,这并不支持现代正则表达式的所有功能。例如,它不能做反向引用。但是,正如文章中所建议的:

“即便如此,使用 Thompson 的 NFA 模拟 大多数正则表达式,并且仅在出现回溯时才带出 需要。一个特别聪明的实现可以将两者结合起来, 诉诸回溯只是为了适应反向引用。”

我怀疑 Firefox 可能会这样做。

【讨论】:

  • 如果他在评论里说了,他不应该把它作为答案发布吗?
  • @Martin.,我提供的是完全不同的文章。而且我从来没有说过他不应该发布答案。
  • 好吧,您在发布链接之前发布了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2011-08-27
  • 2011-12-07
  • 2020-09-03
相关资源
最近更新 更多