2013-08-16 3 views
5

Ich habe eine Regex entwickelt, die pstops Seitenspezifikationen entspricht. (Regex-Leerzeichen nicht signifikant.)Mit geschachtelten benannten Gruppen in einer Regex, möglich, Hierarchie zu navigieren?

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespec> 
    (?<pageno>-?\d+) 
    (?<rotation>[RUL]?)? 
    (?:@(?<scale>\d*(?:\.\d+)))? 
    (?:\(
     (?<xoff>\d*\.?\d+)(?<xunit>in|cm|w|h)? 
     , 
     (?<yoff>\d*\.?\d+)(?<yunit>in|cm|w|h)? 
    \))? 
    \+?)+,? 
)+$ 

.

'Sample string: 
'"4:[email protected](21cm,0)[email protected](21cm,14.85cm),1L(21cm,0)[email protected](21cm,14.85cm)" 

Wie Sie sehen können, gibt es verschachtelte benannte Untergruppen. A pagespec muss zum Beispiel nicht rotation angeben. Ich möchte in der Lage sein, etwas zu der Wirkung, dies zu tun:

If match.Groups("pages").Captures(0).Groups("pagespecs").Captures(1).Groups("rotation").Value > "" 

aber natürlich Captures hat keine Groups Eigenschaft. Gibt es eine Möglichkeit, auf diese Weise auf Untergruppen in der Hierarchie zuzugreifen?

EDIT: Hier ist ein minmal Beispiel (Leerraum signifikant diesmal):

(?<paragraph>(?:(?<sentence>The (?<child>boy|girl) is hungry\.|The (?<parent>mother|father) is angry\.)\s*)+) 

gegen diese Saite Matched:

The boy is hungry. The mother is angry. The girl is hungry. 

ein Spiel erzeugt. Innerhalb dieses Matches

  • Groups("paragraph") hat eine Erfassung, die die gesamte Zeichenfolge abdeckt.
  • Groups("sentence") hat drei Aufnahmen.
  • Groups("child") hat zwei Aufnahmen, boy und girl.
  • Groups("parent") hat eine Aufnahme, mother.

Aber es gibt nichts, das mir sagt, dass die Einzelerfassung für parent für sentence innerhalb der zweiten Erfassung liegt, es sei denn, ich Index und Length für jede Aufnahme beginnen suchen.

EDIT: Hier ist die endgültige Antwort:

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespec> 
    (?<pageno>-?\d+) 
    (?<rotation>[RUL]?) 
    (?:@(?<scale>\d*(?:\.\d+)))? 
    (?:\(
     (?<xoff>\d*\.?\d+)(?<xunit>in|cm|w|h)? 
     , 
     (?<yoff>\d*\.?\d+)(?<yunit>in|cm|w|h)? 
    \))? 
    (?<pageno>)(?<rotation>)(?<scale>)(?<xoff>)(?<xunit>)(?<yoff>)(?<yunit>) 
    \+?)+,? 
(?<pagespec>) 
)+ 

Dies drückt einen NULL auf den pagespec Stapel zwischen den einzelnen page, so können sie mit page korreliert werden; und ein NULL auf jedem der anderen genannten Stacks zwischen jedem pagespec. Gee, Parsing ist schwer ...

+1

Ich denke, es wäre hilfreich für die Nützlichkeit der Frage, wenn Sie dies auf ein minimales Beispiel reduziert haben. Etwas wie das Zusammenpassen von 'xy @ z' mit' (? :(? (? :(? [az]) | -) + | @) + 'würde wahrscheinlich tun (wie in, wie weiß ich, ob' Gruppen ("sub"). Captures (1) 'gehört zu' Groups ("part"). Captures (0) 'oder' (1) '). Aber gute Frage, ich wäre auch an einer Lösung interessiert :). –

Antwort

2

Ich glaube nicht, dass das möglich ist. Soweit ich weiß, haben verschiedene Gruppen keine Beziehung zueinander in Bezug darauf, wie sie in dem Muster verschachtelt sind. Außerdem ist eine solche Hierarchie wäre auch nicht sinnvoll, weil Gruppennamen können in .NET wiederverwendet werden:

(?<group> 
    (?<sub>.) 
)+ 
(?<sub>.) 

ich denke, es wäre irgendwie möglich sein, diese eine hierarchische Struktur als auch darzustellen, aber dies würde die Niederlage Zweck der Stacks, die .NET für Captures bereithält. Vielleicht sollte ich das klarstellen: .NET listet nicht einfach alle Captures einer Gruppe auf - es schiebt sie auf einen Stack, aus dem sie beispielsweise wieder mit (?<-sub>) gepoppt werden können. Nun, wie würdest du das behandeln, wenn eine Instanz einer Gruppe später etwas aus dem Stack herausholt, das schon früher gematcht wurde?Ich denke, es würde für den allgemeinen Fall höchst unintelligent, wenn nicht sogar unmöglich werden.

Was Sie eigentlich wollen, ist Ihre pagespecs Erfassungen gruppieren, indem Sie wie sie eine einzige "Instanz" von pages entsprechen. Sie können durch die sehr Grund, dies zu tun, die die Lösung verhindert, dann würden Sie haben möchten: Sie Gruppen wiederverwenden können:

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespecs> 
    # here goes your actual pagespec pattern 
    [+]?)+ 
    (?<pagespecs>) 
    ,? 
)+$ 

nun am Ende eines jeden page Sie schieben einen leeren String auf den pagespecs Stapel. Da eine normale "Instanz" von pagespecs immer mindestens ein Zeichen enthält, wissen Sie, dass alle leeren Captures von dieser separaten Verwendung von pagespecs stammen müssen. So können Sie nun Captures("pagespecs") durch die leeren String-Elemente teilen und sie dann einfach sequentiell mit den Elementen in Captures("pages") verknüpfen.

+0

Das ist sehr interessant. Ich werde es ausprobieren. –

+0

Beachten Sie, dass eine Seitenangabe nicht gedreht werden muss. Ich könnte eine Seite, fünf Seiten und nur eine Drehung haben. Wie verknüpfe ich diese eine Drehung mit der richtigen Seitenangabe? –

+0

OK, Rotation war ein schlechtes Beispiel - es scheint, dass es als NULL auftaucht, wenn es nicht vorhanden ist. Aber xoff/xunit/yoff/yunit befinden sich in einer unbenannten Capture-Gruppe, die völlig optional ist. Ausschließen, das zerstört die Assoziation. –

Verwandte Themen