在preg_match_all中使用正则表达式变量

时间:2009-11-17 11:33:40

标签: php regex preg-match-all

我正在PHP中构建一个伪变量解析器,以允许在视图中使用干净简单的语法,并为if语句实现了一个引擎。现在我希望能够使用嵌套的if语句,我想到的最简单,最优雅的解决方案是使用identation作为块的标记。

所以这基本上是我在视图中寻找的布局:

{if x is empty}
    {if y is array}
        Hello World
    {endif}
{endif}

该脚本将找到第一个if语句,并在相同深度上与endif匹配。如果它的计算结果为true,那么内部块也将被解析。

现在,我无法在以下代码中设置正则表达式以使用深度:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?){endif}|s', $template, $match);

基本上我希望使用某种变量将([\t ]?)中的第一个匹配放在{endif}之前,如果没有匹配的{endif},请确保该语句不完整与{if ...}相同的深度。

你能帮我完成吗?

3 个答案:

答案 0 :(得分:2)

您通常不能使用正则表达式来解决此问题,因为您定义的语言不是常规的(因为它需要计算{if}{endif}的出现次数。)

您所拥有的是经典匹配括号问题的变体。

您最好使用某种Finite-state machine来跟踪{if}{endif}的出现次数。

答案 1 :(得分:0)

\ 1将包含您的第一场比赛,所以您可以这样做:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?)\1{endif}|s', $template, $match);

但是,这不一定会匹配{endif}的正确出现次数,只会出现前面有正确数量的标签的下一次出现。

答案 2 :(得分:0)

如果你使用明确的“endif”语句,你的块已经关闭,并且没有必要做任何特殊的缩进,只需匹配'/{if.+?}(.+?){endif}/' 。 1 如果,另一方面,你是什么python-like类型缩进块,你可以摆脱{endif}(和括号),只匹配缩进级别

  if condition
      this line is in the if block
      this one too
  this one not

你的表达将是这样的

 /([\t]+)if(.+)\n((\1[\t]+.+\n)+)/

“条件”将匹配2并且语句正文匹配3

1 实际上这应该像/{if}((.(?!{if))+?){endif}/s一样来处理嵌套if。