2016-10-15 3 views
0

Ich baue eine Templating-Engine und würde gerne verschachtelte Logik erlauben.Mit preg_split für Templating-Engine

Ich muss die folgende Zeichenfolge mit "@" für das Trennzeichen teilen, aber ich möchte dieses Trennzeichen ignorieren - behandeln ist wie nur ein anderes Zeichen - wenn es innerhalb der [eckigen Klammern]. Hier

ist die Eingabezeichenfolge:

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

Das Ergebnis sollte wie folgt aussehen:

array(

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

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

    " else [ default condition ] " 

) 

Ich glaube preg_split ist das, was Im suchend aber Hilfe bei der Regex verwenden könnte

+2

Ist es ein Problem ohne einen Versuch? – revo

+0

versuchte das folgende Muster ohne Erfolg:/@ + (?! [^ [@]] *])/X – yevg

Antwort

1

Regex:

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

Output:

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

das ist perfekt! funktioniert und ausgezeichnete Verbindung zur Seite, die sehr nützlich sein wird. Danke!! Ich wünschte, ich hätte den Vertreter zu upvote – yevg

+1

habe gerade genug rep zu upvote und tat, danke nochmal! – yevg

0

To Brauchen Sie verschachtelte Klammern, müssen Sie ein rekursives Muster verwenden.

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

Es passt jedes Segment, nicht einschließlich der führenden @. Es wird auch die letzte Klammer in Gruppe 1 aufgenommen, die Sie ignorieren können.

Verwenden Sie das Muster mit preg_match oder preg_match_all.

0

Vielen Dank für Ihre Antworten! Revo's Antwort hat funktioniert!

Ich konnte nicht mit der Regex selbst kommen und habe stattdessen eine Parser-Funktion, die auch funktioniert. Vielleicht kann es für jemanden nützlich sein:

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