PHP PCRE - Regex升级现在失败(灾难性回溯)+优化

时间:2016-12-12 20:30:13

标签: php regex pcre

我首先发布了这个问题: Regex matching nested beginning and ending tags

WiktorStribiżew完美地回答了这个问题。现在,我想升级我的Regex表达式,以便我的参数支持JSON对象(或者差不多,因为孤独的'{'和'['不受支持)。

我有两个表达式:一个用于配对标签,一个用于孤独的标签。我首先使用配对的,当所有替换完成后,我执行孤独的一个。修改过的孤独的一个在regex101.com(https://www.regex101.com/r/HIEQZk/9)上工作得很好,但配对的告诉我“castatrophic backtracking”(https://www.regex101.com/r/HIEQZk/8),即使在PHP中没有崩溃。

所以任何人都可以帮我优化/修复这个相当庞大的正则表达式。 即使似乎无用的转义,也是因为开始/结束标记和分割器可以自定义,因此必须进行转义。 (配对的不是因为它不是由PHP生成的那个,而是由WiktorStribiżew根据我的修改生成的那个。)

我认为应该优化/修复的唯一部分是我刚刚修改为支持JSON对象的“参数”组。 (在相同的regex101 url的早期版本中可以看到这些测试。这里有一个真正的HTML要解析。)

孤独的表达

~
 \{\{ #Instruction start

   ([^\^\{\}]+) # (Group 1) Instruction name OR variable to reach if nothing else after then
   (?:
     \^
     (?:([^\\^\{\}]*)\^)? #(Group 2) Specific delimiter
     ([^\{\}]*{(?:[^{}\[\]]+|(?3))+}[^\{\}]*|[^\{\}]*\[(?:[^{}\[\]]+|(?3))+\][^\{\}]*|[^\{\}]+) # (Group 3) Parameters
   )?

 \}\} #Instruction end
~xg

配对表达

~{{             # Opening tag start
  (\w+)         # (Group 1) Tag name
  (?:           # Not captured group for optional parameters
   (?:          # Not captured group for optional delimiter
    \^          # Aux delimiter
    ([^^\{\}]?) # (Group 2) Specific delimiter
   )?
   \^           # Aux delimiter
   ([^\{\}]*{(?:[^{}\[\]]+|(?3))+}[^\{\}]*|[^\{\}]*\[(?:[^{}\[\]]+|(?3))+\][^\{\}]*|[^\{\}]+)   # (Group 3) Parameters
  )?
 }}             # Opening tag end
  (             # (Group 4)
   (?>          
     (?R)       # Repeat the whole pattern
     |          # or match all that is not the opening/closing tag
     [^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)*
   )*           # Zero or more times
  )
 {{/\1}}        # Closing tag
~ix

1 个答案:

答案 0 :(得分:1)

尝试使用(?: atomic groups替换您的(?> 非捕获组,以尽可能防止/减少回溯。那些也是非捕获的。和/或在regex101中观看stepscounter / debugger时试用possessive quantifiers

无论您何时不希望引擎返回并尝试其他不同的方式。

This is your updated demo我刚刚将第一个(?:更改为(?>