正则表达式:匹配打开/关闭标记,它接受另一个具有相同名称的打开/关闭标记

时间:2014-05-22 06:17:17

标签: php regex tags

正则表达的粉丝,嗨。 在下面的代码中,有两个父标签(T1-4和T5-6)和一个子标签(T2-3)。

你如何匹配T1-4? 或者一般来说,你如何匹配父标签?

<?php
$subject = '

{{poo}}             # T1
    Hello

    {{poo}}         # T2
        Nested 1
    {{/poo}}        # T3

{{/poo}}            # T4


{{poo}}             # T5
    Bye
{{/poo}}            # T6



';

$p = '!{{(\w+)}}(.*){{/\1}}!s';     // matches T1-6, too greedy
$p = '!{{(\w+)}}(.*?){{/\1}}!s';    // matches T1-3, not what I want

$p = '`(?xs) # xtended

{{(\w+)}}

.*?
(?R)?       # currently working on this one...

{{/\1}}


`';



preg_replace_callback($p, function($match){
    var_dump($match);
}, $subject);

2 个答案:

答案 0 :(得分:3)

这可能就是你要找的东西:

$p = '`(?x)
{{(\w+)}}
# ( # you need probably this capture group later
(?>
    [^{]++
  |
    { (?!{)
  |
    {{ (?! /? \1 \b) # if needed you can add }} in the lookahead
  |
    (?R)
)*
# )
{{/\1}}
`';

答案 1 :(得分:3)

答案略有不同:

~                       # Delimiter
{{(.*?)}}               # Match opening tag and put the name in group 1
(?:                     # Non-capturing group
   (?:(?!{{/?\1}}).)++  # Match anything that's not an opening/closing tag one or more times, no backtracking
   |                    # Or
   (?0)                 # Recurse the whole pattern, same as (?R)
)*                      # Repeat zero or more times
{{/\1}}                 # Match closing tag
~xs

我添加了以下修饰符:

  • x:自由间隔模式,我们的正则表达式中也有精彩的评论。
  • s:将换行符与点匹配。

Online demo