【问题标题】:Recursive PCRE search with patterns带有模式的递归 PCRE 搜索
【发布时间】:2012-05-19 20:35:25
【问题描述】:

这个问题与PCRE有关。

我已经看到了用于此构造的嵌套括号的递归搜索:

\(((?>[^()]+)|(?R))*\)

问题在于,虽然 '[^()]+' 可以匹配任何字符,包括换行符,但您只能匹配单字符字符,例如大括号、方括号、标点符号、单个字母等。

我要做的是用任何类型的模式(例如,'BEGIN' 和 'END' 等关键字)替换 '(' 和 ')' 字符。

我想出了以下结构:

(?xs)  (?# <-- 'xs' ignore whitespace in the search term, and allows '.'
               to match newline )
(?P<pattern1>BEGIN)
(
   (?> (?# <-- "once only" search )
      (
         (?! (?P=pattern1) | (?P<pattern2>END)).
      )+
   )
   | (?R)
)*
END

这实际上适用于如下所示的内容:

BEGIN <<date>>
  <<something>
    BEGIN
      <<something>>
    END <<comment>>
    BEGIN <<time>>
      <<more somethings>>
      BEGIN(cause we can)END
      BEGINEND
    END
  <<something else>>
END

这成功匹配任何嵌套的 BEGIN..END 对。

我分别为 BEGINEND 设置了命名模式 pattern1pattern2。在搜索词中使用 pattern1 效果很好。但是,我不能在搜索结束时使用 pattern2:我必须写出 'END'。

知道如何重写此正则表达式,因此我只需指定一次模式并在代码中“无处不在”使用它们吗?换句话说,所以我不必在搜索的中间和最后都写 END

【问题讨论】:

  • 你好。我的回答有帮助吗?如果不是,你能解释一下怎么做吗?
  • @Kobi:查看您的示例 (regex101.com/r/aG7wP4) 时,它仅匹配最外面的块,除非其中一个模式不匹配(BEGIN 或 END 关键字之一拼写错误或省略) .

标签: regex pcre recursive-regex


【解决方案1】:

要进一步扩展@Kobis 的答案,请参阅以下正则表达式:

(?xs)
(?(DEFINE)
        (?<pattern1>BEGIN)
        (?<pattern2>END)
)
(?=((?&pattern1)
(?:
   (?> (?# <-- "once only" search )
      (?:
         (?! (?&pattern1) | (?&pattern2)) .
      )+
   )*
   | (?3)
)*
(?&pattern2)
))

此正则表达式甚至可以让您获取每个单独数据块的数据!使用第三个反向引用,因为前两个已在定义块中定义。

演示:http://regex101.com/r/bX8mB6

【讨论】:

    【解决方案2】:

    这看起来像是 (?(DEFINE)) 块的一个很好的用例,用于创建此类结构。 Perl 示例如下:

    (?xs)
    (?(DEFINE)
            (?<pattern1>BEGIN)
            (?<pattern2>END)
    )
    (?&pattern1)
    (
       (?> (?# <-- "once only" search )
          (
             (?! (?&pattern1) | (?&pattern2)).
          )+
       )
       | (?R)
    )*
    (?&pattern2)
    

    示例:http://ideone.com/8o9cg

    (请注意我真的不知道任何 perl,并且无法让它在任何在线测试人员的 PHP 上工作)

    另请参阅:http://www.pcre.org/pcre.txt(查找 (?(DEFINE) 0,它看起来不像有页面)


    适用于大多数风格的低技术解决方案是在模式开始时使用前瞻:

    (?=.*?(?P<pattern1>BEGIN))
    (?=.*?(?P<pattern2>END))
    ...
    (?P=pattern1) (?# should work - it was captured )
    

    【讨论】:

      猜你喜欢
      • 2015-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多