获取else else语句的内容

时间:2015-02-26 11:57:16

标签: php regex

我正在尝试为if else语句创建一个bbcode。 这是模式:

\[if([^\b\[\]]+)\](?(?=[\[else\]])(.*?)(?:\[else\])(.*?)|(.*?))\[\/if\]

它应匹配以下字符串:

1: [if %platform.desktop%][icon name="check-square"][/icon][else][icon name="cancel-square"][/icon][/if]

2: [if %platform.desktop%][icon name="check-square"][/icon][/if]

结果应为:

匹配1:

1: " %platform.desktop%"
2: "[icon name="check-square"][/icon]"
3: "[icon name="cancel-square"][/icon]"

第2场比赛:

1: " %platform.desktop%"
2: "[icon name="check-square"][/icon]"

但由于某种原因,else语句没有得到任何结果。 没有匹配2

这应该适用于PHP。

Here is an example.

2 个答案:

答案 0 :(得分:2)

我建议你改变你的正则表达式。

\[if([^\[\]]+)\](?(?=.*\[else\])(.*?)(?:\[else\])(.*?)|(.*?))\[\/if\]

DEMO

我在原始正则表达式中做了哪些更改?

\[if([^\[\]]+)\](?(?=[\[else\]])(.*?)(?:\[else\])(.*?)|(.*?))\[\/if\]
                       ^        ^
  1. 删除上面提到的sqaure括号,这意味着一个字符类。因此[\[else\]]匹配[el,...

  2. 然后在正向前方.*?内添加(?=.*?\[else\])

  3. 以上正则表达式的作用是什么?

    上面的正则表达式使用正则表达式if,else子句。即,如果条件为真,则匹配特定的特定字符块,如果条件为假,则匹配另一特定字符块。

    请参阅上述链接右侧的正则表达式解释。

答案 1 :(得分:2)

当你想构建一个复杂的模式时,我建议你使用命名的子模式,使代码更清晰(并且更容易处理递归,这可能是你想要做的事情所需要的)

$pattern = '~
(?(DEFINE)
    (?<tag>\[(\w+)[^]]*]\g<content>\[/\g{-1}])
    (?<text> [^[]+)
    (?<condition> \[if ([^]]+)]\g<content>(?:\[else]\g<content>)?\[/if] )
    (?<content> (?:\g<text>|\g<condition>|\g<tag>)*)    
)

\[if[ ](?<cond>[^]]+)](?<true>\g<content>)(?:\[else](?<false>\g<content>))?\[/if]
~x';

$str = '1: [if %platform.desktop%][icon name="check-square"][/icon][else][icon name="cancel-square"][/icon][/if]
2: [if %platform.desktop%][icon name="check-square"][/icon][/if]';

if (preg_match_all($pattern, $str, $matches, PREG_SET_ORDER)) {
    foreach ($matches as $m) {
        echo $m['cond'] . ' : ' . $m['true'] . ' : ' . $m['false'] . "\n";
    }
}  

在上面的模式中,(?(DEFINE)...)内的第一部分允许您定义所需的所有子模式而不匹配任何内容。 然后,您可以轻松编写主要模式:

\[if[ ](?<cond>[^]]+)](?<true>\g<content>)(?:\[else](?<false>\g<content>))?\[/if]

用于定义命名子模式的语法是(?<name>...)。要使用子模式,只需编写:\g<name>