Javascript 正则表达式:查找所有 URL 优化

Javascript regex: Find all URLs optimization

本文关键字:URL 优化 查找 正则表达式 Javascript      更新时间:2023-09-26

这个问题是以下帖子的后续:Javascript 正则表达式:查找 标签之外的所有网址 - 嵌套标签

我发现代码:

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

与单独执行httpftp部分相比,效率极低,如下所示:

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

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

以下是 regex101.com 中的示例:

  • 第一种方法 - 6395 步
  • 第二种方法 - 3393 步 + 863 步

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

据我所知,使用 (x|y) 模式可以减少执行长度,但这里可能出于一个奇怪的原因,情况并非如此。

任何帮助将不胜感激。

看来你是灾难性回溯的受害者。

这个正则表达式只需 3492 个步骤即可完成:

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

我所做的只是使第一个组成为原子组,导致引擎在匹配后丢弃所有回溯选项。

这在你的情况下是正确的:你现在可以把它想象成两部分,"找到一个URL",然后"使用负面的前瞻性来决定我们是否要保留它"。当前瞻失败时,您的原始正则表达式将继续回溯到 url 匹配表达式。[^"<'s]+块将产生一些符号,然后它会再次尝试向前看,然后生成更多符号,然后重试,依此类推......

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

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

奖励编辑:进一步改进的编辑,只需 3185 个步骤:

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

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

document.anchors