递归正则表达式:如何设置不匹配的字符串,而不是个别字符

Recursive regular expression: how to set a mismatch with the string, rather than individual characters

我的php代码:

      $exp = 'zzz<pre>sssss<pre>fff</pre>ff</pre>zzz';     
      \preg_match_all("#<pre>((?>[^(?:<pre>)(?:</pre>)]|(?R))*)</pre>#si", $exp, $matches);

        $i = 0;
        foreach ($matches as $item) {           
            foreach ($item as $elem)
            {
                echo "$i  ", \htmlentities($elem), "<br>";
            }
            $i++;
        }

输出:

0 <pre>sssss<pre>fff</pre>ff</pre>

1 sssss<pre>fff</pre>ff

很好 - 正则表达式可以工作并找到嵌套标签 <pre>。但是我有一个问题:

[^(?:<pre>)(?:</pre>)]

我可以用字符< / p r e >设置一个dismath,但是我需要用字符串<pre></pre>设置一个dismach。因此,如果我在原文中至少添加符号 pr,正则表达式将无法正常工作。

示例: $exp = zzz<pre>ssspss<pre>fff</pre>ff</pre>zzz; // p inside ssspss

输出

0 <pre>fff</pre>

1 fff

告诉我,如何构建正则表达式来设置不匹配的字符串,而不是单个字符?

可能您想使用 negative lookahead instead of the negated character class:

~<pre>((?>(?!</?pre).|(?R))*)</pre>~si

test at regex101.com

您的正则表达式没有按预期工作,因为 [^(?:<pre>)(?:</pre>)] 匹配任何不在 [^ 否定 character class 中的字符。任何不属于以下之一的:</pre)(?,:,>


旁注:正则表达式不适合解析任意嵌套 html。考虑 using a parser.