【问题标题】:Using preg_split for templating engine使用 preg_split 进行模板引擎
【发布时间】:2016-10-15 16:50:15
【问题描述】:

我正在构建一个模板引擎,并希望允许嵌套逻辑。

我需要使用“@”作为分隔符来拆分以下字符串,但我想忽略这个分隔符 - 将其视为另一个字符 - 如果它在 [方括号] 内。

这是输入字符串:

@if(param1>=7) [ something here @if(param1>9)[ nested statement ] ] @elseif(param2==true) [ 2st condition true ] @else [ default condition ] 

结果应该是这样的:

array(

   " if(param1>=7) [ something here @if(param1>9)[ nested statement ] ] ",

   " elseif(param2==true) [ 2st condition true ] ",

   " else [ default condition ] "

)

我相信 preg_split 是我正在寻找的,但可以使用正则表达式的帮助

【问题讨论】:

  • 不试就出问题了?
  • 尝试了以下模式无济于事:/@+(?![^[@]]*])/x

标签: php regex templates preg-split


【解决方案1】:

正则表达式:

@(?> if | else (?>if)? ) \s*  # Match a control structure
(?> \( [^()]*+ \) \s*)?  # Match statements inside parentheses (if any)
\[  # Match start of block
(?:
    [^][@]*+  # Any character except `[`, `]` and `@`
    (?> \\.[^][@]* )* (@+ (?! (?> if | else (?>if)? ) ) )? # Match escaped or literal `@`s
    |  # Or
    (?R)  # Recurs whole pattern
)*  # As much as possible
\]\K\s*  # Match end of container block

Live demo

PHP:

print_r(preg_split("~@(?>if|else(?>if)?)\s*(?>\([^()]*+\)\s*)?\[(?:[^][@]*+(?>\\.[^][@]*)*(@+(?!(?>if|else(?>if)?)))?|(?R))*\]\K\s*~", $str, -1, PREG_SPLIT_NO_EMPTY));

输出:

Array
(
    [0] => @if(param1>=7) [ something here @if(param1>9)[ nested statement ] ]
    [1] => @elseif(param2==true) [ 2st condition true ]
    [2] => @else [ default condition ]
)

PHP live demo

【讨论】:

  • 这太完美了!作品和极好的网站链接,这将非常有用。感谢您!!希望我有代表支持
  • 刚刚获得了足够的代表来支持并投了赞成票,再次感谢!
【解决方案2】:

要匹配嵌套括号,您需要使用递归模式。

(?:(\[(?:[^[\]]|(?1))*])|[^@[\]])+

它将匹配每个段,不包括前导 @。它还将最后一个括号捕获到第 1 组中,您可以忽略它。

将模式与preg_matchpreg_match_all 一起使用。

【讨论】:

    【解决方案3】:

    感谢您的回复! Revo 的回答奏效了!

    我自己无法提出正则表达式,而是构建了一个同样有效的解析器函数。也许它对某人有用:

    function parse_context($subject) { $arr = array(); // array to return
    
        $n = 0;  // number of nested sets of brackets
        $j = 0;  // current index in the array to return, for convenience
    
        $n_subj = strlen($subject);
        for($i=0; $i<$n_subj; $i++){
            switch($subject[$i]) {
                case '[':
                    $n++;
                    $arr[$j] .= '[';
                    break;
                case ']':
                    $n--;
                    $arr[$j] .= ']';
                    break;
                case '@':
                    if ($n == 0) {
                        $j++;
                        $arr[$j] = '';
                        break;
                    }
                default: $arr[$j].=$subject[$i];
            }
        }
        return $arr;
    
    } // parse_context()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-24
      • 2011-01-05
      • 2016-08-31
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      相关资源
      最近更新 更多