Php 嵌套PCRE正则表达式问题

Php 嵌套PCRE正则表达式问题,php,regex,nested,Php,Regex,Nested,我有一个自定义模板引擎 它抓住了这一点: @function(argument1 argument2 ...) @get(param:name) @get(param:@get(sub:name)) 这是: @function(argument1 argument2 ...) Some stuff @with(nested:tag) @foreach(arguments as value) More stuff : @get(value) @/for

我有一个自定义模板引擎

它抓住了这一点:

@function(argument1 argument2 ...)
@get(param:name)
@get(param:@get(sub:name))
这是:

@function(argument1 argument2 ...)

    Some stuff @with(nested:tag)

    @foreach(arguments as value)
        More stuff : @get(value)
    @/foreach

    @function(other:args)
        Same function name (nested)
    @/function

@/function
使用此模式(PCRE/PHP):


这个正则表达式捕获了几乎所有的结果。但是当我有更多的嵌套(或不嵌套)标记时,它就什么也抓不到了例如,当我执行2个嵌套的
@foreach(var:name)@/对于每个
,正则表达式将失败,具体取决于标记内容
空格

,使用命名子模式有时更清晰。我建议你使用这个:

~
@(?<com>\w+)                 # command name
\s*                          # possible white characters before args
(?: \( (?<args>[^)]*) \) )?+ # eventual parameters
(?:
    (?<content>(?:[^@]+|(?R))*+) # content (maybe empty)
    @/\g{com}                    # close the command
)?+                          # optional
~

使用这种语法,如果要在底层提取元素,只需将主模式更改为:
@(?\g)\s*(?\g)?(?:(?\g)@/\g{com})
(注意:要获得其他级别,请将其放在前瞻中)

您是否尝试简单地检查输入是否遵循特定格式?或者你想从中提取一些东西?正则表达式通常不能处理嵌套模式。有些RE引擎有递归,但我认为PHP不支持。@Barmar:PCRE确实支持。@AmalMurali我提取
函数
参数
,以及标记内容(如果有的话)。@Barmar PHP支持带
?(R)
的递归和其他类似原子组的东西。感谢您的回复。我尝试了你的每一次编辑。最后一个是工作。除了使用这种标记之外,
@load(@get(layout:control))
。这里,标记内容与最后的
args
括号不匹配。(每次尝试时,我都无法同时匹配嵌套的内容标记和嵌套的args标记)@user2715533:如果参数部分中允许使用命令,您可以将args描述替换为:
(?(?>[^@)]+++(?=@)(?R))*)
而不是
(?[^)]*)
哦,是的!多谢各位。工作起来很有魅力。@user2715533:描述语言时最好使用命名模式和
(?(定义)…)
语法。我将发布一个例子。谢谢你非常有用的回答。我会听从你的建议。
~
@(?<com>\w+)                 # command name
\s*                          # possible white characters before args
(?: \( (?<args>[^)]*) \) )?+ # eventual parameters
(?:
    (?<content>(?:[^@]+|(?R))*+) # content (maybe empty)
    @/\g{com}                    # close the command
)?+                          # optional
~
$pattern = <<<'EOD'
~
(?(DEFINE)
    (?<command_name> \w+ )
    (?<inline_command> @ \g<command_name> \s* \g<params>? )
    (?<multil_command> @ (\g<command_name>) \s* \g<params>? \g<content> @/ \g{-1} )
    (?<command> \g<multil_command> | \g<inline_command> )

    (?<other> [^@()]+ ) 
    (?<param> \g<other> | \g<command> )
    (?<params> \( \s* \g<param> (?: \s+ \g<param> )* \s* \) )

    (?<content> (?: \g<other> | \g<command> )* )
)
# main pattern
\g<command>
~x
EOD;