嵌套引号内的子模式正则表达式匹配

Subpattern Regex match within nested quotes

我正在从一些带有许多不必要的嵌套 [QUOTE] 标签的旧论坛软件升级,我想通过正则表达式(使用 PHP preg_replace)去除这些标签。其中大部分已经完成,但我正在努力处理以下类型。

post 中有嵌套的引用块,但只需要保留顶级 [QUOTE] 内容(因为一些嵌套的引用有 3 或 4 层深)。

例如:

Here is some normal post content

[QUOTE]
This is an appropriate quote
[/QUOTE]

Here is more post content

[QUOTE]
This is a a valid quote, as it's only 1 level deep.
   [QUOTE="User 2"]
   Here's an unnecessary nested quote.
       [QUOTE]
       Here's a 3nd level unnecessary nested quote.
       [/QUOTE]
   [/QUOTE]
[/QUOTE]

Here is more post content

我想去掉第二层和第三层的嵌套引号,但不知道怎么做。

我对 有一些很好的建议,但我一直无法修改正则表达式模式以适应这个例子。

与您链接的正则表达式具有相同的限制(引号内没有其他标签),您可以使用

((?:\[QUOTE\]|\G(?!^))[^][]+)((\[QUOTE[^][]*\](?:[^][]++|(?2))++\[/QUOTE\])) 

进行搜索,然后 </code> 仅替换嵌套的引号。</p> <p>这基本上匹配单独组中的最外引号和递归中的内部引号,因此只允许删除它们。</p> <p>见<a href="https://regex101.com/r/y39Xaf/2" rel="nofollow noreferrer">https://regex101.com/r/y39Xaf/2</a></p> <p>我添加了一个测试用例,在一个外引号内有两个不同的引号。</p> <p>关于 <code>((?:\[QUOTE\]|\G(?!^))[^][]+) 的小故障:

  • 所有内容都包含在捕获组中以允许重新插入
  • (?:\[QUOTE\]|\G(?!^) 匹配文字 [QUOTE] 或上一个匹配的结尾
  • [^][]+ 匹配任何普通文本

是的,您可以使用链接答案中的相同正则表达式并将其应用 两次 并结合一些编程逻辑:

<?php

$regex = '~
        (\[QUOTE[^][]*\]
        (?:[^][]++|(?1))++
        \[/QUOTE\])
        ~x';

$data = preg_replace_callback($regex, 
    function($match) use($regex) {
        return $match[0][0] . preg_replace($regex, '', substr($match[0], 1));
    },
    $your_data_string_here);

echo $data;
?>


这会产生您的示例:

Here is some normal post content

[QUOTE]
This is an appropriate quote
[/QUOTE]

Here is more post content

[QUOTE]
This is a a valid quote, as it's only 1 level deep.

[/QUOTE]

Here is more post content


这里的想法是匹配每个引号标签(嵌套或不嵌套),然后将相同的表达式应用于匹配的字符串,但偏移量为 +1。当我们取一个子字符串时,只会找到下一个嵌套的 [QUOTE] 集,然后将其替换。

A demo on regex101.com and on ideone.com 进一步阐明了这一点。