【问题标题】:Javascript regex: Find all URLs optimizationJavascript 正则表达式:查找所有 URL 优化
【发布时间】:2016-06-27 14:49:53
【问题描述】:

这个问题是以下帖子的后续问题: Javascript regex: Find all URLs outside <a> tags - Nested Tags

我发现代码:

\b((https?|ftps?):\/\/[^"<\s]+)(?![^<>]*>|[^"]*?<\/a)

与像这样为httpftp 部分单独执行它相比,效率极低:

\b(https?:\/\/[^"<\s]+)(?![^<>]*>|[^"]*?<\/a)

\b(ftps?:\/\/[^"<\s]+)(?![^<>]*>|[^"]*?<\/a)

以下是 regex101.com 上的示例:

但是,在我的一个 HTML 页面中,这些代码比较为 85628 步与 7258 + 795 步,这太疯狂了。

据我所见,使用(x|y) 模式会减少执行时间,但这里可能出于一个奇怪的原因,否则会这样。

任何帮助将不胜感激。

【问题讨论】:

标签: javascript html regex hyperlink multipart-alternative


【解决方案1】:

看来你是catastrophic backtracking的受害者。

这个正则表达式只需要 3492 个步骤就可以解决问题:

\b(?>(https?|ftps?):\/\/[^"<\s]+)(?![^<>]*>|[^"]*?<\/a)

我所做的只是将第一组设为atomic group,导致引擎在匹配后丢弃所有回溯选项。

在您的情况下是正确的:您现在可以将其视为两部分,“找到一个 URL”然后“使用否定前瞻来决定我们是否要保留它”。当前瞻失败时,您的原始正则表达式将继续回溯到 url 匹配表达式。 [^"&lt;\s]+ 块会产生一些符号,然后它会再次尝试前瞻,然后产生更多的符号,然后再试一次,依此类推...

添加 https?|ftps? 部分使其变得更糟的原因是,这提供了一个额外的回溯源(丢失了可选的 s),从而允许所有后来的回溯再次发生。

您知道 regex101.com 在左侧工具栏上有一个“正则表达式调试器”选项吗?如果你使用它,它会解释如何你的正则表达式匹配,所以你可以(就像我刚刚做的那样)找出疯狂的回溯在哪里。

额外修改:进一步改进,仅需 3185 步:

\b(?>ht|f)tps?:\/\/(?>[^"<\s]+)(?![^<>]+>|[^"]*?<\/a)

【讨论】:

  • 非常感谢!我知道在调试器的帮助下也发现了灾难性的回溯,但无法解决。
  • 诀窍是弄清楚你的正则表达式的哪些部分可以像这样成为原子的部分。您的示例很简单,但是许多正则表达式需要大量回溯才能正常工作。有时可以稍微调整一下正则表达式以使其更适合这个技巧。
【解决方案2】:

如果您要查找文档中的所有链接,那么解决方案就是这样。 它返回一个数组

document.anchors

【讨论】:

猜你喜欢
  • 2013-07-17
  • 2011-12-14
  • 1970-01-01
  • 2016-09-04
  • 2017-09-18
  • 2012-01-30
  • 1970-01-01
相关资源
最近更新 更多