【问题标题】:Subpattern Regex match within nested quotes嵌套引号内的子模式正则表达式匹配
【发布时间】:2018-01-16 14:54:39
【问题描述】:

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

帖子中有嵌套的引用块,但只需要保留顶级 [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

我想去掉第 2 级和第 3 级嵌套引号,但不知道如何。

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

【问题讨论】:

    标签: php regex preg-replace


    【解决方案1】:

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

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

    搜索,然后$1 仅替换嵌套引号。

    这基本上匹配单独组中的最外引号,并且仅匹配递归中的内部引号,因此只允许删除它们。

    https://regex101.com/r/y39Xaf/2

    我在一个外部引号内添加了一个带有两个不同引号的测试用例。

    ((?:\[QUOTE\]|\G(?!^))[^][]+) 的小故障:

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

    【讨论】:

    • 谢谢 Sebastian,非常聪明,它可以在单个正则表达式中做到这一点!我现在将在一些帖子上对此进行测试:)
    【解决方案2】:

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

    <?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] 集合然后替换。

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

    【讨论】:

    • 多么聪明的做法啊!非常简单的解决方案。谢谢一月:)
    • 我刚刚对所有帖子进行了测试,看起来效果很好,只是有点小问题。如果嵌套引号中有方括号(例如,对于其他标签),则它会阻止删除该嵌套引号。是否有解决方法,或者这是一个必要的妥协?
    • @IanCun:我会说边缘情况变得越来越复杂,你可能会更好地使用解析器。话虽如此,您可以捕获标签名称并最终匹配它,例如\[(\w+)[^][]*\](?:[^][]++|(?R))++\[/\1\] - 这就是您想要的吗?
    • 非常感谢@Jan。不幸的是,我无法正常工作 (ideone.com/6Xn10W),但也许可以在单独的正则表达式中去除这些标签并运行原始脚本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多