首页 > 解决方案 > 小组赛过长导致灾难性回溯

问题描述

我创建了一个正则表达式模式,允许我从任何 HTML 字符串中提取内联样式:https ://regex101.com/r/YBdbxS/4 -为了更好地理解上下文,我创建了一个自定义 WordPress 插件来提取内联样式从当前页面并将其放入自己的文件中。

要使正则表达式再次起作用,只需#myid { color: green; }在上面的代码段中删除一个,它就会按预期工作。

正则表达式工作得非常好,但现在我得到一个catastrophical backtracing错误,因为内联样式太长(我使用的 WordPress 主题使用了很长的内联样式,所以我无法触摸内联样式本身;例如将其拆分为多个样式)。

临时解决方案

我通过设置为类似的值找到了解决方法pcre.backtrack_limit

ini_set("pcre.backtrack_limit", "23001337");

但这似乎是不好的做法。

是否有任何替代方案,例如锚定模式,因此它不会从组中第一个找到的匹配项一次又一次地回溯(.*?)

标签: phpregexwordpress

解决方案


正如 Wiktor 所提到的,答案是对非捕获组使用负面展望?!?:

<style([^>]*)>([^<]*(?:<(?!\/style>)[^<]*)*)<\/style>
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|       |  *1
                                            ^^^^^^^^^  *2
  1. 捕获之前的所有内容</style>。使用与您的“关闭”模式相同的内容*2
  2. 你的“关闭”模式

推荐阅读