2015-05-04 13 views
5

Diciamo che ho il seguente espressione regolare:Get subpattern gruppo denominato da oggetto .NET regex

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

allora ho la stringa:

"Space123" 

Ecco il mio programma:

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 
    } 
} 

Quello che voglio sapere è se c'è un modo per ottenere la parte dell'espressione regolare che corrisponde? In questo caso:

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

Non riesco a trovarlo da nessuna parte nell'oggetto, ma si potrebbe pensare che sarebbe accessibile.

+0

Non sono sicuro della tua domanda ... l'espressione regolare che corrisponde è lo schema che hai usato 'Spazio (? [0-9] {1,3}) '. E 'quello di cui hai bisogno? –

+0

Esatto, ma voglio estrarlo dall'oggetto, solo la parte di acquisizione, ovvero ( [0-9] {1,3}), non l'intera stringa. – Matt

+0

Per quanto ne so, le espressioni regolari sono generalmente implementate costruendo una macchina a stati dietro le quinte che analizza la sintassi e sputa un risultato booleano. Pertanto, una singola espressione regolare è fondamentalmente il proprio sistema autonomo. L'unico modo che posso vedere per fare ciò che vuoi è di creare più espressioni regolari più piccole e abbinarle tutte al testo separatamente. – cmcquillan

risposta

5

È possibile sfruttare il metodo Regex.ToString() che memorizza il modello di espressione regolare. I gruppi di capure con nome ei rispettivi indici possono essere ottenuti utilizzando Regex.GetGroupNames() e Regex.GetGroupNumbers().

Inoltre, abbiamo bisogno di un array/elenco dei gruppi di cattura all'interno del modello regex, ecco perché sto aggiungendo rxPairedRoundBrackets regex per catturare tutti i testi all'interno di parentesi tonde senza caratteri di escape.

suggerisco questo codice per ottenere il sotto-regola regex per una specifica nome gruppo (modificare: ora, anche la manipolazione annidati gruppi parentetici escape!):

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); 
} 

E qui è il codice per la vostra caso:

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); 
} 

uscita:

enter image description here