2016-10-15 151 views
0

我正在構建模板引擎,並希望允許嵌套邏輯。使用preg_split模板引擎

我需要使用分隔符「@」來分隔下面的字符串,但是想要忽略這個分隔符 - treat只是另一個字符 - 如果它在[方括號內]。

這裏是輸入字符串:

@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是林尋找,但可以使用幫助與正則表達式

+2

這是一個沒有嘗試的問題嗎? – revo

+0

嘗試以下模式無濟於事:/ @ +(?![^ [@]] *])/ x – yevg

回答

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("[email protected](?>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

+0

這是完美的!作品和網站的優秀鏈接將非常有用。謝謝!!希望我有代表upvote – yevg

+1

剛剛得到足夠的代表upvote並做了,再次感謝! – yevg

0

要匹配嵌套括號,你需要使用遞歸模式。

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

它會匹配每個細分市場,不包括領先的@。它還會將最後一個括號捕獲到組1中,您可以忽略它。

使用preg_matchpreg_match_all的模式。

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()