In .NET RegEx kann ich eine Groups-Sammlung von einem Capture-Objekt erhalten?

8

.NET bietet in seiner RegularExpression-Implementierung eine Capture-Sammlung, sodass Sie alle Instanzen einer bestimmten Wiederholungsgruppe statt nur der letzten Instanz abrufen können. Das ist großartig, aber ich habe eine sich wiederholende Gruppe mit Untergruppen und ich versuche, auf die Untergruppen zu kommen, da sie unter der Gruppe verwandt sind und keinen Weg finden können. Irgendwelche Vorschläge?

Ich habe mir eine Reihe anderer Fragen angesehen, z. B .:

aber ich habe keine zutreffende Antwort gefunden, entweder affirmativ ("Ja, hier ist wie") oder negativ ("Nein, kann nicht gemacht werden.").

Für ein künstliches Beispiel sage ich, dass ich eine Eingabezeichenfolge habe:

%Vor%

wobei "abc" und "fgh" für Text stehen, den ich im größeren Dokument ignorieren möchte, "d" und "e" für den Bereich von Interesse und innerhalb dieses Interessenbereichs "xn [n]" kann beliebig oft wiederholt werden. Es sind diese Zahlenpaare in den "x" Bereichen, an denen ich interessiert bin.

Also analysiere ich es mit diesem regulären Ausdruck:

%Vor%

wird genau eine Übereinstimmung im Dokument finden, aber die "x" Gruppe viele Male erfassen. Hier sind die drei Paare, die ich in diesem Beispiel extrahieren möchte:

  • 1, 2
  • 3
  • 5, 6

Aber wie kann ich sie bekommen? Ich könnte folgendes machen (in C #):

%Vor%

und da ich die Gruppe "x" referenziere, bekomme ich diese Zeichenfolgen:

  • x 1 2
  • x 3
  • x 5 6

Aber das bringt mich nicht bei den Zahlen selbst. Also könnte ich "fir" und "sec" unabhängig von "x" machen:

%Vor%

erhalten:

  • 1
  • 3
  • 5
  • 2
  • 6

aber dann kann ich nicht wissen, dass es das zweite Paar ist, dem die "4" fehlt und nicht eines der anderen Paare.

Was soll ich tun? Ich weiß, dass ich das in C # oder sogar mit einem zweiten Regex-Test in der "x" -Gruppe leicht analysieren könnte, aber da der erste RegEx-Lauf bereits die ganze Arbeit gemacht hat und die Ergebnisse bekannt sind, scheint es einen Weg zu geben das Match-Objekt zu manipulieren, um das zu bekommen, was ich brauche.

Und denken Sie daran, dies ist ein künstliches Beispiel, der Fall der realen Welt ist etwas komplexer, also würde es einfach ein Schmerz sein, nur zusätzlichen C # -Code zu werfen. Aber wenn die vorhandenen .NET-Objekte das nicht können, dann muss ich das nur wissen und ich werde meinen Weg fortsetzen.

Gedanken?

    
bob 17.12.2012, 17:57
quelle

4 Antworten

5

Ich bin mir einer voll integrierten Lösung nicht bewusst und konnte sie nach einer kurzen Suche nicht finden, aber dies schließt die Möglichkeit nicht aus, dass es eine gibt.

Mein bester Vorschlag ist, die Eigenschaften Index und Length zu verwenden, um übereinstimmende Captures zu finden. Es scheint nicht wirklich elegant, aber Sie könnten in der Lage sein, nach dem Schreiben einiger Erweiterungsmethoden einen ziemlich guten Code zu entwickeln.

%Vor%

Hier eine mögliche Lösung mit der folgenden Erweiterungsmethode.

%Vor%

Jetzt können Sie den Code wie folgt umschreiben.

%Vor%     
Daniel Brückner 17.12.2012, 18:48
quelle
3

Wird es immer ein Paar gegen ein einzelnes sein? Sie können separate Erfassungsgruppen verwenden. Natürlich verlieren Sie die Reihenfolge der Artikel mit dieser Methode.

%Vor%

Wenn Sie die Bestellung brauchen, würde ich wahrscheinlich mit Blams Vorschlag gehen, einen zweiten regulären Ausdruck zu verwenden.

    
Adam Prescott 17.12.2012 18:36
quelle
2

Ich schlage vor, Sie schauen in das einzigartige zu .net regex die Balanced Groups.

Hier ist eine Regex, die das verwendet, um die Übereinstimmung zu stoppen, wenn die Gruppe (entweder eine Nichtstelle oder ein X) gefunden wird, um die Gruppe zu schließen. Dann werden die Matches über die Captures nach Bedarf aufgerufen:

%Vor%     
OmegaMan 17.12.2012 19:35
quelle
1

Ich habe die Antwort von OmegaMan gesehen und weiß, dass Sie einen C # -Code anstelle einer Regex-Lösung bevorzugen. Aber ich wollte trotzdem eine Alternative präsentieren.

In .NET können Sie benannte Gruppen wiederverwenden. Jedes Mal, wenn etwas mit dieser Gruppe gefangen wird, wird es auf den Stapel geschoben (darauf bezog sich OmegaMan auf "Bilanzkreise"). Sie können damit eine leere Aufnahme für jeden gefundenen x auf den Stapel schieben:

%Vor%

Nun, nachdem x gefunden wurde, schiebt (?<d>) eine leere Aufnahme auf den Stapel. Hier ist der Console.WriteLine -Ausgang (eine Zeile pro Capture):

%Vor%

Wenn Sie also durch Regex.Match(input, pattern).Groups["d"].Captures gehen und leere Strings notieren, wissen Sie, dass eine neue Gruppe von Zahlen begonnen hat.

    
Martin Ender 17.12.2012 20:40
quelle

Tags und Links