2015-05-04 3 views
5

Lassen Sie uns sagen, dass ich die folgende regex haben:Erhalten Sie benannte Gruppe Unter-Pattern von .NET Regex Objekt

var r = new Regex("Space(?<entry>[0-9]{1,3})"); 

Dann habe ich die Zeichenfolge:

"Space123" 

Hier ist mein Programm:

void Main() 
{ 
    Regex r = new Regex("Space(?<entry>[0-9]{1,3})", RegexOptions.ExplicitCapture); 
    foreach (Match m in r.Matches("Space123")){ 
     m.Groups["entry"].Dump(); //Dump() is linqpad to echo the object to console 
    } 
} 

Was ich wissen möchte, ist, wenn es eine Möglichkeit gibt, den regulären Ausdruck Teil zu bekommen, die übereinstimmte? In diesem Fall:

(?<entry>[0-9]{1,3}) 

Ich kann es nirgendwo im Objekt finden, aber man würde denken, dass es zugänglich wäre.

+0

Ich bin mir nicht sicher über Ihre Frage ... der passende Ausdruck ist das Muster, das Sie 'Space (? [0-9] {1,3}) '. Ist das was du brauchst? –

+0

Richtig, aber ich möchte es aus dem Objekt, nur den Capture-Teil, nämlich ( [0-9] {1,3}), nicht die ganze Zeichenfolge. – Matt

+0

Soweit ich weiß, werden reguläre Ausdrücke normalerweise implementiert, indem hinter den Kulissen eine Zustandsmaschine aufgebaut wird, die die Syntax analysiert und ein boolesches Ergebnis ausspuckt. Daher ist ein einzelner regulärer Ausdruck grundsätzlich sein eigenes in sich geschlossenes System. Der einzige Weg, den ich sehen kann, um zu tun, was Sie wollen, wäre, mehrere kleinere reguläre Ausdrücke zu machen und sie alle separat mit Ihrem Text abzugleichen. – cmcquillan

Antwort

5

Sie können die Regex.ToString()-Methode verwenden, die das Muster für reguläre Ausdrücke speichert. Benannte Capure-Gruppen und ihre jeweiligen Indizes können unter Verwendung von Regex.GetGroupNames() und Regex.GetGroupNumbers() erhalten werden.

Außerdem benötigen wir ein Array/eine Liste der Capture-Gruppen innerhalb des Regex-Musters, deshalb füge ich rxPairedRoundBrackets Regex hinzu, um alle Texte innerhalb von nicht-runden Klammern zu erfassen.

schlage ich diesen Code die Regex Unter-Pattern für eine bestimmte namens Gruppe zu erhalten (bearbeiten: jetzt, auch verschachtelte unescaped klammerten Gruppen Handhabung!):

var rxPairedRoundBrackets = new Regex(@"(?sx)(?=((?<=[^\\]|^)\(
     (?> 
      (?! (?<!\\)\(| (?<!\\)\)) . 
      | 
      (?<!\\)\((?<Depth>) 
      | 
      (?<!\\)\) (?<-Depth>) 
     )* 
     (?(Depth)(?!)) 
     (?<!\\)\)))+"); 
var r = new Regex(@"(?<OuterSpace>Spa(?<ce>ce))(?<entry>\([0-9]{1,3}\))", RegexOptions.ExplicitCapture); 
var bracketedGrps = rxPairedRoundBrackets.Matches(r.ToString()).Cast<Match>().Select(p => p.Groups[1].Value); 
var GroupDict = r.GetGroupNames().Zip(r.GetGroupNumbers(), (s, i) => new { s, i }) 
           .ToDictionary(item => item.s, item => item.i); 
foreach (Match m in r.Matches("My New Space(123)")) 
{ 
    var id = "entry"; 
    var grp = m.Groups[id]; // Just to see the group value 
    var groupThatMatched = bracketedGrps.ElementAt(GroupDict[id] - 1); 
} 

Und hier ist der Code für Ihre Fall:

r = new Regex("Space(?<entry>[0-9]{1,3})", RegexOptions.ExplicitCapture); 
bracketedGrps = rxPairedRoundBrackets.Matches(r.ToString()).Cast<Match>().Select(p => p.Groups[1].Value); 
GroupDict = r.GetGroupNames().Zip(r.GetGroupNumbers(), (s, i) => new { s, i }) 
          .ToDictionary(item => item.s, item => item.i); 
foreach (Match m in r.Matches("Space123")) 
{ 
    var id = "entry"; 
    var grp = m.Groups[id]; 
    var groupThatMatched = bracketedGrps.ElementAt(GroupDict[id] - 1); 
} 

Ausgang:

enter image description here