2012-06-15 17 views
7

Mam serię zgrupowanych wartości, które mają określony format i chciałbym użyć pojedynczego wyrażenia do przechwycenia ich w grupy. Na przykład, mam -group1 -group2 -group3 i próbuję użyć czegoś podobnego do (-[\s\S]{1,}?) Jest to w zasadzie pozwala mi przechwycić cały ciąg w jednej grupie, ale chciałbym być w stanie wycofać każdy z tych wartości osobno. Pomyślałem, że ? zmusiłoby go do braku chciwości, a zatem podzieliłoby wzorzec dopasowania na trzy oddzielne grupy (na przykład). Na razie po prostu powtarzam odwołanie (-[\s\S]*?), ale wydaje się, że powinno być bardziej elegancki wyrażenie.
Dzięki!Wyrażenie regularne w celu wybrania powtarzających się grup

+0

Jest to nieco niejasne. Czy możesz pokazać przykładowy tekst i oczekiwany wynik grupowania, łącznie z tym, co chcesz odzyskać? –

+0

Nawiasem mówiąc, '[\ s \ S]' mówi "Dopasuj dowolną spację lub nie-spację". Pomyśl o tym. ;) – qJake

Odpowiedz

14

masz szczęście bo C# jest jednym z kilku języków (jeśli nie jedyny), który obsługuje podwyrażenie przechwytuje

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

.NET API może być postrzegana jako następująco

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

Z twojego pytania nie wynika, co dokładnie chcesz dopasować, ale to powinno zacząć. Zapytaj ponownie, jeśli utkniesz.

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

Ten ouputs

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

Jak widać (Grupa 1, przechwytywania 0) i (Grupa 1, Przechwytywanie 1) oferują poszczególne zrzuty z grupy (i nie ostatni jak w większości języki)

Ten adres myślę o tym, co można opisać jako „aby móc wsteczne każdej z wartości oddzielnie”

(użyć wstecznych okres, ale nie sądzę, jesteś dążenie do AR wzór wyrównania prawy?)

+1

+1. Wierzę, że o to też prosił. Na marginesie PHP oferuje to z '' preg_match_all (...) '' funkcja; za pomocą flagi 'PREG_SET_ORDER'' zwraca tablicę wielowymiarową, pierwszą tablicę zawierającą pierwszy zbiór, drugą tablicę zawierającą drugi zestaw itd. (Inne flagi zezwalają na różne reprezentacje). Domyślam się, że jeśli .NET i PHP to zaimplementowało, mają też inne języki. –

+0

@ acheong87 Dobry komentarz, dodam go do odpowiedzi, aby nie obrażać innych języków :) Mam to od eksperta od regexp Jana Goyvaertsa, że ​​.NET był wyjątkowy w tym aspekcie, ale nie jestem wystarczająco aktywny na innych platformach, aby to poprzeć w górę. – buckley

+2

@ acheong87, to nie to samo. 'preg_match_all()' stosuje wielokrotnie wyrażenie regularne i zwraca zebrane wyniki, podobne do metody 'Matches()' .NET. OP chce wykonać * jeden * mecz, który pochłonie cały ciąg, a następnie wydzieli pojedyncze przechwyty. .NET zapewnia 'CaptureCollection' w tym celu, ale PHP nie ma odpowiednika. –

0

Spróbuj tego:

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

Twoja pierwsza grupa przechwytywania będzie mieć, co chcesz (-group1, -group2, etc).

Jeśli chcesz mieć większą kontrolę nad tym, co pozwoli po - zmień .+? do, na przykład, [a-zA-Z0-9]+? tylko dopasować znaki alfanumeryczne.

2

Z regex .NET (i prawie tylko .NET) można użyć:

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

Grupa 1 będzie zawierać listę wszystkich dopasowanych podciągów.

A może po prostu za pomocą Matches jest wystarczająca w przypadku:

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