【问题标题】:Difficult PHP Nested Regular Expression [duplicate]困难的PHP嵌套正则表达式[重复]
【发布时间】:2019-05-17 03:12:33
【问题描述】:

给定以下字符串:

{start} SubPattern1 {end} 
....
{start} SubPattern2 {end}
....
{start} {start}SubPattern3{end} {end}

我需要找到给出以下结果的正则表达式:

preg_match_all($regex, $string, $result);

print_r($result);

array(2
    0 => array(3
        0 => {start} SubPattern1 {end}
        1 => {start} SubPattern2 {end}
        2 => {start} {start}SubPattern3{end} {end}
    )
    1 => array(3
        0 => SubPattern1 
        1 => SubPattern2 
        2 => {start}SubPattern3{end} 
    )
)

谢谢!

编辑

出于视觉目的,我写了一个多行字符串。但即使所有文本都在单行字符串中,我也需要该表达式有效。例如:

{start}SubPattern1{end}{start}SubPattern2{end}{start}{start}SubPattern3{end}{end}

【问题讨论】:

  • 谢谢!有什么尝试吗?
  • 我不明白为什么这个问题被标记为重复。

标签: php regex nested preg-match-all


【解决方案1】:

您可以匹配 {start} 和 {end} 并使用捕获组并对模式使用递归:

{start}((?:(?:(?!{(?:start|end)}).)+|(?R))*){end}

例如:

$string = <<<DATA
{start} SubPattern1 {end} 
{start} SubPattern2 {end}
{start} {start}SubPattern3{end} {end}
DATA;

preg_match_all('/{start}((?:(?:(?!{(?:start|end)}).)+|(?R))*){end}/', $string, $result);
print_r($result);

说明

  • {start} 字面匹配
  • (开始抓包
    • (?:非捕获组
      • (?:非捕获组
        • (?!{(?:start|end)}). 否定前瞻断言右边的内容不是 {start} 或 {end}。如果是这种情况,请匹配任何字符。
      • )+|(?R) 关闭非捕获组并重复 1 次以上或 | 递归整个模式
    • )*关闭非捕获组并重复0+次
  • )关闭捕获组
  • {end} - 字面匹配

Regex demo

结果:

Array
(
    [0] => Array
        (
            [0] => {start} SubPattern1 {end}
            [1] => {start} SubPattern2 {end}
            [2] => {start} {start}SubPattern3{end} {end}
        )

    [1] => Array
        (
            [0] =>  SubPattern1 
            [1] =>  SubPattern2 
            [2] =>  {start}SubPattern3{end} 
        )

)

Php demo

【讨论】:

  • 你能添加关于递归正则表达式的解释吗?从最后半小时开始,我正在努力解决它。如果可以的话,它会很有帮助。提前致谢
  • @CodeManiac 我已经添加了解释。
  • @Thefourthbird 效果很好。但是当子模式中存在大括号时,模式不匹配。例如:{start} Pattern{1} {end} {start}{end} 之间的任何内容。感谢您的宝贵时间。
  • @JorgeLuis 我已经更新了我的答案。
  • @Thefourthbird 简直太完美了!非常感谢!
【解决方案2】:

你可以用这个

^{start}(.*){end}$
  • ^ - 字符串开头。
  • {start} - 匹配 {start}
  • (.*) - 匹配除新行以外的任何内容。 (捕获组)。
  • {end} - 匹配 {end}
  • $ - 字符串结束。

Demo

【讨论】:

  • 谢谢!但这仅适用于模式在不同行中的情况。即使字符串在一行中,我也需要表达式有效。我会在原帖中声明。
  • @JorgeLuis 看看regex101.com/r/8ULlDM/3
  • 这很接近,但在最后一个嵌套模式中不起作用。再次感谢。
猜你喜欢
  • 2012-10-18
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多