递归标记内容

时间:2012-05-22 10:21:52

标签: php regex preg-match

我正在寻求改进以下正则表达式,因为我现在也希望匹配嵌套代码:

'%{if:\s*"\'([^\']*)\' == \'([^\']*)\'"}((?:(?!{else}|{/endif}).)*){else}((?:(?!{/endif}).)*){/endif}%sei'

基本匹配:

{if: "'x' == 'y'"}
    a
{else}
    b
{/endif}

{if: "'x' == 'y'"}
    c
{/endif}

但是,我希望以某种方式递归,因此嵌套语句也可以在不破坏任何内容的情况下进行匹配(如果添加了嵌套语句,它会中断)。

!=也会有类似的表达。

我发现这个http://www.devnetwork.net/viewtopic.php?f=38&t=102670&sid=02b7c691a2be894336c694700f8f911a#p551340符合<div>标签,但有点不确定如何调整它以适应我的正则表达式...

2 个答案:

答案 0 :(得分:0)

如果将嵌套限制在某个预定深度(这可能是也可能不是一个坏主意),您可以将它与正则表达式匹配。否则,你不能。您提供的链接将HTML与正则表达式匹配,这通常是使用的,但known通常是个坏主意。如果您不想使用其他形式的解析,请考虑匹配最内层的ifs,替换为某些内容并再次匹配。

答案 1 :(得分:0)

在这种情况下使用正则表达式(PCRE)并不是最佳的,因为您需要为每个嵌套级别重新解析内部内容(使用正确解析器的原因之一会更好)。

也就是说,它可以通过以下模式完成:

~
{if:\s*+
    (?<condition>
        [^{}]++
    )
}

(?<then>
    (?:
        (?:(?!{if:[^{}]++}|{else}|{/endif}).)*+
        (?R)*+
    )*+
)

(?:
    {else}
    (?<else>
        (?:
            (?:(?!{if:[^{}]++}|{else}|{/endif}).)*+
            (?R)*+
        )*+
    )
)?+

{/endif}
~six

Perl示例@ ideone

在此文中

if: "'x' == 'y'"}
    a
{else}
    b
{/endif}

{if: "'x' == 'y'"}
    c
{/endif}

{if:minimal}{else}{/endif}

{if: "'nested' == 'things'"}
    {if: "'x' == 'y'"}x{if:minimal}{else}{/endif}x{/endif}
{else}
    b{if: "'x' == 'y'"}c{/endif}{if: "'x' == 'y'"}c{/endif}
{/endif}

{if:foo} unbalanced {if:bar}ignores first if{/endif}

匹配

*** matched if:
  * cond: "'x' == 'y'"
  * then:
    a

  * else:
    b

*** matched if:
  * cond: "'x' == 'y'"
  * then:
    c

*** matched if:
  * cond: minimal
  * then:
  * else:
*** matched if:
  * cond: "'nested' == 'things'"
  * then:
    {if: "'x' == 'y'"}x{if:minimal}{else}{/endif}x{/endif}

  * else:
    b{if: "'x' == 'y'"}c{/endif}{if: "'x' == 'y'"}c{/endif}

*** matched if:
  * cond: bar
  * then: ignores first if