2012-11-19 10 views
6

Sto cercando di scrivere un espressione regolare che corrisponda un elenco separato da virgole di parole e catturare tutte le parole. Questa linea dovrebbe essere abbinato    apple , banana ,orange,peanut  e cattura dovrebbe essere apple, banana, orange, peanut. Per fare questo io uso seguente espressione regolare:Odd comportamento espressione regolare - corrisponde solo prima e l'ultima acquisizione del gruppo

^\s*([a-z_]\w*)(?:\s*,\s*([a-z_]\w*))*\s*$ 

Si abbina con successo la stringa, ma tutto ad un tratto solo apple e peanut vengono catturati. Questo comportamento è visto sia in C# che in Perl. Quindi presumo che mi manchi qualcosa su come funziona la corrispondenza con regexp. Qualche idea? :)

risposta

3

Il valore in match.Groups[2].Value è solo l'ultimo valorecatturato dal secondo gruppo.

Per trovare tutti i valori, guarda match.Groups[2].Captures[i].Value dove in questo caso i gamme 0-2. (. Così come match.Groups[1].Value per il primo gruppo)

(! 1 per la domanda, ho imparato qualcosa oggi)

+0

+1 io non ero sicuro se .net ha questa funzione ed è stato troppo pigro per controllare. – stema

+0

@stema Non mi ero nemmeno reso conto che si trattava di un problema, pensavo che tutti i valori si sarebbero presentati in 'Gruppi'! – Rawling

+0

Grazie per avermi segnalato alla raccolta di '.Captures'! Alla fine mi è capitato di usare la stessa espressione regexp mentre inserivo la domanda e poi eseguivo for for (int i = 1; i bazzilic

2

Sei repeating your capturing group, ad ogni partita ripetuto il contenuto precedente viene sovrascritto. Quindi solo l'ultima partita del tuo secondo gruppo di cattura è disponibile alla fine.

potete modificare il vostro secondo gruppo di cattura per

^\s*([a-z_]\w*)((?:\s*,\s*(?:[a-z_]\w*))*)\s*$ 

allora il risultato sarebbe "banana, arancia, arachidi" nel secondo gruppo. Non sono sicuro, se vuoi questo.

Se si desidera verificare che la stringa ha quel modello ed estrarre ogni parola. Lo farei in due passaggi.

  1. Controllare il motivo con la vostra espressione regolare.

  2. Se il motivo è corretto, rimuovere gli spazi bianchi iniziali e finali e dividere lo \s*,\s*.

3

Prova questo:

string text = " apple , banana ,orange,peanut"; 

var matches = Regex.Matches(text, @"\s*(?<word>\w+)\s*,?") 
     .Cast<Match>() 
     .Select(x => x.Groups["word"].Value) 
     .ToList(); 
+2

PS: Questo è un buon sito per testare le espressioni regolari in .NET: [Regex Hero] (http://regexhero.net/tester/) –

+0

Ho usato [questo] (http://regexpal.com/) – bazzilic

+1

Mi piace [questo] (http://regexstorm.net/tester?p= ([AZ] {2}) ([0-3]) (0 [1-9] | [12] \ d | 3 [01]) (0 [1-9] | 1 [0-2]) (\ d {2}) (\ d {3}) & I = KT2140210456). –

2

Semplice regexp:

(?:^| *)(.+?)(?:,|$)

Spiegazione:

?: # Non capturing group 
^| * # Match start of line or multiple spaces 
.+ # Capture the word in the list, lazy 
?: # Non capture group 
,|$ # Match comma or end of line 

Nota: Rublular è un bel sito web per testare questo genere di cose.

Problemi correlati