2017-04-26 1 views
2

ich einen String der folgenden FormErhalten Sie alle Wörter, die eine bestimmte Präfix Gruppe haben

$string = "This is {test} for [a]{test2} for {test3}."; 

Ich will, muss alle geschweiften Klammern bekommen, die nicht von eckigen Klammern vorangestellt werden. Daher möchte ich in der obigen Zeichenfolge {test} und {test3}, aber nicht [a]{test2} erhalten.

Ich fand in der Antwort https://stackoverflow.com/a/977294/2311074, dass dies mit negativem Lookahead möglich sein könnte. Also habe ich versucht

$regex  = '/(?:(?!\[[^\}]+\])\{[^\}]+\})/'; 
    echo preg_match_all($regex, $string, $matches) . '<br>'; 
    print_r($matches); 

aber das gibt mir immer noch alle drei geschweiften Klammern.

Array ([0] => Array ([0] => {Test} [1] => {Test2} [2] => {test3}) )

Warum funktioniert das nicht?

+0

@ WiktorStribiżew danke für Ihre ausführliche Antwort. Ich hole das Thema negative Lookahead auf. Ich werde antworten/upvote Ihre Antwort, sobald ich es verstanden habe. – Adam

+0

Bitte fragen Sie, was unklar ist - ich werde für einige Stunden online sein. –

Antwort

1

Der Grund Ihrer regex versagt ist, dass es jede { Spiele (gefolgt mit 1+ nicht } s und dann ein }), wenn es nicht eine Folge der Muster innerhalb des negativen Look-Ahead-Start ist ein [, 1+ Zeichen anders als } und dann ein ] (und es ist immer wahr, so erhalten Sie alle {...} Teilstrings als Ergebnis).

Verwendung (*SKIP)(*FAIL) technique:

\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^\}]+} 

die regex demo See.

Einzelheiten:

  • \[[^]]*]\{[^}]+}(*SKIP)(*F) - passend
    • \[ - ein [
    • [^]]* - 0+ Zeichen andere als ]
    • ]\{ - ]{ Teilzeichenfolge
    • [^}]+ - 1+ Zeichen andere als ]
    • } - eine wörtliche }
    • (*SKIP)(*F) - PCRE Verben den Text so weit angepasst Verwerfen und zwingt den Motor auf der Suche nach dem nächsten Spiel von der aktuellen Position zu gehen (als ob eine Übereinstimmung aufgetreten)
  • | - oder
  • \{[^\}]+}:
    • \{ - ein {
    • [^\}]+ - 1+ Zeichen andere als } und
    • } - eine wörtliche }.

Siehe PHP demo:

$string = "This is {test} for [a]{test2} for {test3}."; 
$regex  = '/\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^}]+}/'; 
echo preg_match_all($regex, $string, $matches) . "\n"; 
print_r($matches[0]); 

Ausgang:

2 
Array 
(
    [0] => {test} 
    [1] => {test3} 
) 
+0

Danke. Ich habe gerade gemerkt, dass ich einen Fehler in meinem Rexgex hatte, ich wollte eigentlich ''/(? Adam

+0

Ich bin froh, dass ich helfen konnte. '(* SKIP) (* FAIL)' ist die einzige korrekte Möglichkeit, etwas in PCRE zu negieren, das keinen Zugriff auf ein negatives Lookback mit unendlicher Breite hat, ohne Annahmen zu treffen. –

2

Wenn Sie sicher sind, würden geschweiften Klammern Öffnen nur mit einem Paar von eckigen Klammern (symmetrisch) vorangestellt werden dann ein negativer Lookbehind wird den Job erledigen:

(?<!]){[^}]*} 

Live demo

+0

Sehr schöner Hinweis, danke :)! Ist es nicht notwendig, ']' und '}' zu entkommen? – Adam

Verwandte Themen