Qui ci sono le stringhe che mi piacerebbe estrarre il contenuto tra i tag {{if}}
e {{\if}}
, intendo il primo e l'ultimo (quelli interni saranno ricontrollati dal motore):
La regex è: \{\{(if)\}\}(((?!\{\{\/?\1\}\})[\s\S])*(\{\{\1\}\}(?2)*\{\{\/\1\}\})*((?!\{\{\/?\1\}\})[\s\S])*)\{\{\/\1\}\}
MODIFICA 3: ho rimosso l'obbligo di supportre i TAG senza terminarne uno. Ho riformattato la domanda per gli utenti futur, per capire alcuni commenti qui sotto, vedere la prima versione del post
Inoltre, ce l'ho per funzionare tutti e tre allo stesso tempo, dandomi tre match, che non funziona sul sito web regex101. Le interruzioni di row devono essere supportte all'interno della partita. Però, potrei accettare che solo le ultime due combinate iif
due match perché potrei cambiare il tag di solo if
per iif
.
La mia altra soluzione non sta usando le espressioni regolari, ma mi piacerebbe farlo se è ansible.
Puoi usare
~{{ # Opening tag start (\w+) # (Group 1) Tag name \^ # Aux delimiter ([^^\{\}]?) # (Group 2) Specific delimiter \^ # Aux delimiter ([^\{\}]+) # (Group 3) Parameters }} # Opening tag end ( # (Group 4) (?> (?R) # Repeat the whole pattern | # or match all that is not the opening/closing tag [^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)* )* # Zero or more times ) {{/\1}} # Closing tag ~ix
Guarda la demo regex
In generale, l'espressione si basa sulla ricorsione e un token goloso temperato . [^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)*
è un srotolato (?s:(?!{{/?\1}}).)*
model che corrisponde a qualsiasi carattere ( .
) Che non è il punto di partenza per una sequenza di caratteri {{TAG}}
o {{/TAG}}
.
Non hai bisogno di un modificatore DOTALL per questo model in quanto non c'è .
nel model.
Ecco una demo PHP :
$re = '~{{(\w+)\^([^^\{\}]?)\^([^\{\}]+)}}((?>(?R)|[^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)*)*){{/\1}}~i'; $str = "before {{if^^p1^p2}} IN1; {{if^ ^p1}} {{iif}} IN3 {{/if}} IN1-1 {{/if}} after\nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{/if}} after\nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{if^ ^p1}} IN4 {{/if}} {{/if}} after"; preg_match_all($re, $str, $matches); print_r($matches);