REGEX PCRE嵌套文本匹配的递归表达式

时间:2016-06-26 21:39:14

标签: regex pcre

所以我想尝试做这样的事情(是的,包括新行):

匹配#1

START
    START
        stuff
    STOP
    more stuff
STOP

匹配#2

START
    START
        stuff
    STOP
    more stuff
STOP

这是我走了多远

START(.*?^(?:(?!STOP).)*$|(?R))|STOP参数" g" " M" " I"和" s"

问题是在STOP与最后一次" STOP"匹配后,我无法匹配任何内容。在整篇文章中。

这是一个regex101示例

https://regex101.com/r/vD4nX6/1

我会赞美一些指导

提前致谢

1 个答案:

答案 0 :(得分:3)

这是一个与您的示例匹配的模式:

^\h*START\h*\n(?:\h*+(?!(?:START|STOP)\h*$)[^\n]*\n|(?R)\n)*\h*STOP\h*$

使用/mg标记(住在https://regex101.com/r/iK9tK5/1)。

背后的想法:

^                                  # beginning of line
\h* START \h* \n                   # "START" optionally surrounded by horizontal whitespace
                                   #   on a line of its own
(?:                                # between START/STOP, every line is either "normal"
                                   #   or a recursive START/STOP block
    \h*+                           # a normal line starts with optional horizontal whitespace
    (?!                            #   ... not followed by ...
        (?: START | STOP ) \h* $   #   "START" or "STOP" on their own
    )
    [^\n]* \n                      # any characters, then a newline
|
    (?R) \n                        # otherwise it's a recursive START/STOP block
)*                                 # we can have as many items as we want between START/STOP
\h* STOP \h*                       # "STOP" optionally surrounded by horizontal whitespace
$                                  # end of line

我已经\h*+占有所有权,以避免意外地将" STOP"\h*的0次迭代进行匹配,而不是"STOP"(他们是'然后是" STOP"(带空格))。 +强制\h尽可能多地匹配,因此必须占用空间。

或者,您可以将\h*拉入前瞻:(?!\h*(?:START|STOP)\h*$)
这也可行,但随后前瞻将跳过任何空格以查看它们是否后跟START / STOP,只是让[^\n]*外面再次查看相同的空格。在\h*+开头,我们匹配这些空格一次,没有回溯。我想这是微观优化。