2012-06-15 12 views
7

Ho una serie di valori raggruppati che seguono un formato specifico e vorrei usare una singola espressione per catturarli in gruppi. Ad esempio, ho -group1 -group2 -group3 e sto tentando di utilizzare qualcosa di simile a (-[\s\S]{1,}?) Questo mi permette di catturare l'intera stringa in un singolo gruppo, ma mi piacerebbe poter ritrasferire ciascuno dei valori separatamente. Ho pensato che lo ? avrebbe dovuto renderlo non-goloso e, quindi, dividere la corrispondenza del modello in tre gruppi separati (ad esempio). Per ora sto semplicemente ripetendo il riferimento (-[\s\S]*?) ma sembra che ci dovrebbe essere un'espressione più elegante.
Grazie!Espressione regolare per selezionare gruppi ripetuti

+0

Questo è un po 'vago. Puoi mostrare del testo di esempio e il risultato del raggruppamento previsto, compreso ciò che intendi per il riferimento? –

+0

A proposito, '[\ s \ S]' dice "Abbina qualsiasi spazio o carattere non spaziale". Pensaci. ;) – qJake

risposta

14

Siete fortunati perché C# è una delle poche lingue (se non l'unico) che supporta subexpression cattura

https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.capture(v=vs.110)

L'API NET può essere visto come segue

Matches 
    Groups (most regex engines stop here) 
     Captures (unique for .NET) 

Non è chiaro dalla tua domanda che cosa vuoi abbinare esattamente ma questo dovrebbe iniziare. Chiedi di nuovo se sei bloccato.

string input = "-group1 -group2 "; 
    string pattern = @"(-\S*\W){2}"; 
    foreach (Match match in Regex.Matches(input, pattern)) 
    { 
    Console.WriteLine("Match: {0}", match.Value); 
    for (int groupCtr = 0; groupCtr < match.Groups.Count; groupCtr++) 
    { 
     Group group = match.Groups[groupCtr]; 
     Console.WriteLine(" Group {0}: {1}", groupCtr, group.Value); 
     for (int captureCtr = 0; captureCtr < group.Captures.Count; captureCtr++) 
      Console.WriteLine("  Capture {0}: {1}", captureCtr, 
          group.Captures[captureCtr].Value); 
    }      
    } 

Questo ouputs

Match: -group1 -group2 
    Group 0: -group1 -group2 
     Capture 0: -group1 -group2 
    Group 1: -group2 
     Capture 0: -group1 
     Capture 1: -group2 

Come si può vedere (Gruppo 1, cattura 0) e (Gruppo 1, Cattura 1) offrire le singole cattura di un gruppo (e non l'ultimo come nella maggior parte lingue)

Questo indirizzo penso a ciò che si descrive come "essere in grado di backreference ciascuno dei valori separatamente"

(si utilizza il termine backreference, ma non credo che si sta puntando per ar modello di eplacement giusto?)

+1

+1. Credo che sia quello che stava chiedendo anche lui. Per inciso, PHP offre questo con il suo '' preg_match_all (...) '' funzione; usando il flag '' PREG_SET_ORDER'', restituisce un array multidimensionale, il primo array che contiene il primo set, il secondo array che contiene il secondo set, ecc. (Altri flag consentono rappresentazioni diverse.) La mia ipotesi è quella se .NET. e PHP l'hanno implementato, anche altri linguaggi. –

+0

@ acheong87 Buon commento, lo aggiungo alla risposta per non offendere altre lingue :) L'ho preso dall'esperto regexp Jan Goyvaerts che .NET era unico su questo aspetto ma non sono abbastanza attivo su altre piattaforme per supportare questo su. – buckley

+2

@ acheong87, non è la stessa cosa. 'preg_match_all()' applica ripetutamente l'espressione regolare e restituisce i risultati raccolti, in modo simile al metodo 'Matches()' di .NET. L'OP vuole eseguire una corrispondenza * una * che consumerà l'intera stringa, quindi rompere le singole acquisizioni. .NET fornisce 'CaptureCollection' per questo scopo, ma PHP non ha equivalenti. –

0

Prova questo:

(-.+?)(\s|$) 

Il tuo primo gruppo di cattura avrà ciò che si vuole (-group1, -group2, ecc).

Se si desidera un maggiore controllo su cosa consentire dopo lo -, modificare [a-zA-Z0-9]+?, ad esempio, per corrispondere solo caratteri alfanumerici.

2

Con regex .NET (e quasi solo NET) è possibile utilizzare:

(?:(-\S+)\s*)+ 

Gruppo 1 conterrà un elenco di tutte le sottostringhe corrispondenti.

O forse solo utilizzando Matches è sufficiente nel tuo caso:

var re = new Regex(@"-\S+"); 
var matches = re.Matches(str);