嵌套引号内的子模式正则表达式匹配
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 进一步阐明了这一点。
我正在从一些带有许多不必要的嵌套 [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 进一步阐明了这一点。