正则表达式 - 递归 - 具有多个结尾的嵌套匹配

Regex - Recursion - nested matches with multiple ending

这是我关于 Whosebug 的第一个问题,所以请在这里公开。另外我的母语不是英语。

(16.02.2022) ANSWERhttps://regex101.com/r/4FRznK/1 来自 Comment on Answer)。特别感谢 Casimir et Hippolyte 的帮助!我希望我能联系到你。

\[if \s+ (?<cond> [^]]* ) ]

(?<content> [^[]*+ 
        (?: (?R) [^[]*
          | \[ (?! /if] | else (?:if)?  \b) [^[]*
        )*+
)
(?<rest> 
    (?: \[elseif \s+ [^]]* ] \g<content> )*+
    (?: \[else] \g<content> )?+
    \[/if]
)

(15.02.2022) 更新: 我摆弄了下面提出的解决方案,并取得了更进一步的进展。似乎字符串长度有限制,可以在没有任何灾难性回溯的情况下轻松匹配。

我更新了我的 Regex101 以显示最近的进展。也许你们中的一个人对如何解决这个问题有想法。 https://regex101.com/r/wYzA3e/4

旁注: 我确实有一个工作功能,但我的目标是在优化和可靠性方面找到一个更快的解决方案。我当前的功能(在我看来)需要很长时间才能完成任务,并且非常依赖 strpos 来完成任务。如果有更便宜(就性能而言)的 PHP 内部函数解决方案,我实际上并不想使用 third-party 函数。 因此,即使您建议我使用替代方法,也请善待并提供提示,说明您明确指的是这些方法。谢谢!

(14.02.2022) 原文: 我的正则表达式遇到以下困难: 这是字符串(“true”and/or“false”实际上不在字符串中,但有助于简化):

**[if true]**
    [if true]
        [if false]
        [else]
        [/if]
    *[elseif false]*
        [if true]
        [/if]
    [else]
    [/if]
**[elseif false]**
[/if]
**[if false]**
    [if false]
    [else]
    *[/if]*
**[else]**
    [if true]
    [/if]
[/if]

我标记了想要的比赛 (**) 和我得到的 (*)

在这种情况下,我只想匹配最外层的 parent [if XXXX].([else]|[elseif XXX]|[/if]) 语句及其相应的结尾,可以是[else]、[elseif XXX] 或 [/if]。现在我不关心内部 [if XXX] 因为当 parent 为假时我不需要检查它们。

当 运行 我的正则表达式:

/\[if (.*?)\](((?R)|.)*?)(\[\/if\]|\[else\]|\[elseif )/gs 

它匹配 parents [if XXX] 和其中任何 [elseif XX]、[else]、[/if] 的不连贯组合。

作为组,我确实需要匹配 > 每个 X [if XXX] > [if XXX] 和匹配的 [END] 以及 [END] 之间的内容。

由于我不完全理解递归,非常感谢您的帮助。非常感谢!

您可以在此处尝试正则表达式(已更新): https://regex101.com/r/wYzA3e/4

这可能很接近?
它还捕获外部结束标记。
但是不知道如何在不破坏递归的情况下避免这种情况。

\[(if|elseif|else) ?(.*?)\](((?R)|[^\[\]])*?)(?:.(?=\[else.*?\])|\[\/if\])

测试 regex101 here

当模式开始有点复杂时,可以使用两个功能:

  • 详细模式(x 修饰符)
  • 对子模式的引用或对命名子模式的更好引用 (\g<name>)

通常有了这两个功能,事情会变得更清晰,模式也更容易构建:

~
\[if \s+ [^]]* ]

(?<content> [^[]*+ (?: (?R) [^[]* )*+ )
(?: \[elseif \s+ [^]]* ] \g<content> )*+
(?: \[else] \g<content> )?+

\[/if]
~x

demo

请注意,(?R) 只不过是对子模式的引用,只是这次子模式是整个模式。