使用preg_split来模板化引擎

时间:2016-10-15 16:50:16

标签: php regex templates preg-split

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

我需要使用“@”分隔以下字符串作为分隔符,但是想要忽略这个分隔符 - 对待它只是另一个字符 - 如果它在[方括号]中。

这是输入字符串:

@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是我正在寻找的,但可以使用正则表达式的帮助

3 个答案:

答案 0 :(得分:1)

正则表达式:

#include <stdio.h>
#include <stdlib.h>

void printMaze(char **maze, int width, int height){
    for (int x = 0; x < width; x++){
        for (int y = 0; y < height; y++){
            putchar(maze[x][y]);
        }
    }
}

int main(int argc, char *argv[]){
    int width, height;
    scanf("%d %d", &height, &width);
    char originalMaze[width][height];
    for (int y = 0; y < height; y++){
        for (int x = 0; x < width; x++){
            originalMaze[x][y] = getchar();
        }
        getchar();
    }
    printMaze(originalMaze, width, height);
    return 0;
}

Live demo

PHP:

@(?> 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

输出:

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

PHP live demo

答案 1 :(得分:0)

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

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

它将匹配每个细分,不包括领先@。它还会将最后一个括号捕获到组1中,您可以忽略它。

将模式与preg_matchpreg_match_all一起使用。

答案 2 :(得分:0)

谢谢你的回复! 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()