如何使用正则表达式创建循环


How to create loop with regular expression?

老实说,我想我应该先问一下这个问题的语法。

但如果你能理解我的意思,请用合适的标题编辑。

是否有一种方法可以使模式可以分割这样的文本。

{{START}}
    {{START}}
        {{START}}
            {{START}}
            {{END}}
        {{END}}
    {{END}}
{{END}}

所以每个{{START}}匹配它的{{END}}从内到外最后!

如果我不能只使用regex。那用PHP呢?

谢谢你。

这超出了正则表达式的能力,正则表达式只能解析正则语法。你所描述的需要一个下推自动机(正则语言由一个正则自动机定义)。

您可以使用正则表达式来解析单个元素,但是"深度"部分需要由具有内存概念的语言来处理(PHP可以很好地处理这个问题)。

因此,在您的解决方案中,正则表达式将仅用于识别您的标记,而跟踪深度和确定END标记属于哪个元素的真正逻辑必须是您的程序本身。

这是可能的!您可以使用递归正则表达式拥有每个级别的内容:

$data = <<<LOD
{{START1}}
    aaaaa
    {{START2}}
        bbbbb
        {{START3}}
            ccccc
            {{START4}}
                ddddd
            {{END4}}
        {{END3}}
    {{END2}}
{{END1}}
LOD;
$pattern = '~(?=({{START'd+}}(?>[^{]++|(?1))*{{END'd+}}))~';
preg_match_all ($pattern, $data, $matches);
print_r($matches);

解释:

part: ({{START'd+}}(?>[^{]++|(?1))*{{END'd+}})

模式的这一部分描述了{{START#}}{{END#}}的嵌套结构

(             # open the first capturing group
{{START'd+}}  
(?>           # open an atomic group (= backtracks forbidden)
    [^{]++    # all that is not a { one or more times (possessive)
  |           # OR
    (?1)      # refer to the first capturing group itself
)             # close the atomic group
{END'd+}}     # 
)             # close the first capturing group

现在的问题是,您不能仅用这一部分捕获所有级别,因为字符串的所有字符都被模式消耗了。换句话说,你不能匹配字符串的重叠部分。

问题是将所有这些部分包装在零宽度断言中,该断言不会消耗像向前看(?=...)这样的字符,结果:

(?=({{START'd+}}(?>[^{]++|(?1))*{{END'd+}}))

这将匹配所有级别