2017-02-05 1 views
1

Ich habe eine Antwort für this question gepostet, wo das OP eine Regex zu verschiedenen Blöcken von JSON-esque Daten mit einer Bedingung, die eine der Eigenschaften hat, übereinstimmen soll ein bestimmter Wert.Regex mit Bilanzgruppen funktioniert mit negativem Lookahead, aber nicht positivem Lookahead (.net Dialekt)

Vereinfachen die Frage ein wenig - einige Beispieldaten wie folgt annehmen:

layer { foo { bar { baz } } qux } 
layer { fee { bar { baz } } qux } 
layer { foo { bar { baz foo } } qux { quux quuux } } 
{} 
zip { layer { zop { layer {yeehah { foo } } } } } 
zip { layer{ zop { layer {yeehah { fee } } } } } 

Die Regex für layer { .. stuff with nested data ...} entsprechen sollten, aber nur dort, wo es ist ein Datenelement von foo.

in der Antwort Meine regex ist:

layer\s*{(?>{(?<c>)|[^{}](?!fee)+|}(?<-c>))*(?(c)(?!))}

, die anstelle von positiv identifiziert Matches enthalten foo schließt nur jene fee enthält. Das ist in Ordnung, wenn alle nicht fee -Elemente sind foo -Elemente, aber das war nicht der Fall für die Frage auf dem anderen Thread. Meine Lösung fügt im Grunde alle anderen nicht foo -Items auf die negative Vorschau wie folgt aus:

layer\s*{(?>{(?<c>)|[^{}](?!fee|blah|bloh|bluh|etc)+|}(?<-c>))*(?(c)(?!))}

Aber das ist unpraktisch, wenn Sie die Datenelemente wissen nicht im Voraus, die Sie ausschließen möchten. Ich habe versucht, mit einem positiven Look-Ahead:

layer\s*{(?>{(?<c>)|[^{}](?=foo)+|}(?<-c>))*(?(c)(?!))}

Aber das funktioniert nicht.

Meine Frage: kann mir jemand helfen, die Regex neu zu schreiben, um für die z. layer { foo { bar } } Elemente mit einem positiven Lookahead - oder muss ich etwas anderes verwenden?

Antwort

1

Sie brauchen nicht die positive Vorschau, Verwendung Capturing und Stack mit bedingter Kontrolle:

layer\s*{(?<f>\s*foo)?(?>{\s*foo(?<f>)(?<c>)|{(?<c>)|[^{}]+|}(?<-c>))*(?(c)(?!))(?(f)|(?!))} 

Siehe regex demo

POIs:

  • layer\s*{(?<f>\s*foo)? - eine optionale benannte Gruppe „f "wird hinzugefügt, die foo erfasst, wenn nach der layer { + optionale Anzahl von Leerzeichen vorhanden.
  • (?>{\s*foo(?<f>)(?<c>)| - der erste Zweig innerhalb der Atomgruppe ist ein Zweig, der einen { (Beginn eines Knotens) übereinstimmt, der mit foo folgt, und wenn angepaßt, 2 Stapel inkrementiert: f (foo Gruppe) und c (offene Klammer Gruppe).
  • (?(f)|(?!)) - Nachdem die ausgeglichene Zahl von { und } überprüft wurde, überprüft dieses bedingte Konstrukt, ob der foo-Stapel nicht leer ist, und wenn es nicht leer ist, ist alles in Ordnung, die Übereinstimmung wird zurückgegeben, wenn nicht, ist die Übereinstimmung gescheitert.