Java regex przechwytuje indeksy grup


113

Mam następujący wiersz,

typeName="ABC:xxxxx;";

Muszę znaleźć słowo ABC,

Napisałem następujący fragment kodu,

Pattern pattern4=Pattern.compile("(.*):");
matcher=pattern4.matcher(typeName);

String nameStr="";
if(matcher.find())
{
    nameStr=matcher.group(1);

}

Więc jeśli wstawię group(0), dostaję, ABC:ale jeśli to postawię , tak group(1)jest ABC, więc chcę wiedzieć

  1. Co to 0i co 1oznacza? Byłoby lepiej, gdyby ktoś wyjaśnił mi dobre przykłady.

  2. Wzorzec wyrażenia regularnego zawiera w sobie znak :, więc dlaczego group(1)wynik go pomija? Czy grupa 1 wykrywa wszystkie słowa w nawiasach?

  3. Jeśli więc wstawię jeszcze dwa nawiasy, na przykład \\s*(\d*)(.*): to czy będą dwie grupy? group(1)zwróci (\d*)część i group(2)zwróci (.*)część?

Fragment kodu został podany w celu wyjaśnienia moich nieporozumień. To nie jest kod, z którym mam do czynienia. Powyższy kod można zrobić String.split()w dużo łatwiejszy sposób.

Odpowiedzi:


182

Przechwytywanie i grupowanie

Grupa przechwytywania (pattern) tworzy grupę, która ma właściwość przechwytywania .

Powiązany, który często można zobaczyć (i używać), to (?:pattern), który tworzy grupę bez właściwości przechwytywania , stąd nazywana grupą nieprzechwytywaną .

Grupa jest zwykle używana, gdy trzeba powtórzyć sekwencję wzorców, np. (\.\w+)+Lub określić, gdzie zmiana powinna obowiązywać, np. ^(0*1|1*0)$( ^, Then 0*1lub 1*0, then $) versus ^0*1|1*0$( ^0*1lub 1*0$).

Grupa przechwytywania, oprócz grupowania, nagra również tekst dopasowany do wzorca wewnątrz grupy przechwytywania (pattern). Korzystanie z przykładem, (.*):, .*tenis ABCi :tenis :, a ponieważ .*znajduje się wewnątrz grupy przechwytywania (.*), tekst ABCjest zapisywany do grupy przechwytywania 1.

Numer grupy

Cały wzorzec jest zdefiniowany jako grupa o numerze 0.

Dowolna grupa przechwytywania we wzorcu rozpoczyna indeksowanie od 1. Indeksy są definiowane przez kolejność nawiasów otwierających grup przechwytywania . Jako przykład, oto wszystkie 5 grup przechwytywania według poniższego wzoru:

(group)(?:non-capturing-group)(g(?:ro|u)p( (nested)inside)(another)group)(?=assertion)
|     |                       |          | |      |      ||       |     |
1-----1                       |          | 4------4      |5-------5     |
                              |          3---------------3              |
                              2-----------------------------------------2

Numery grup są używane w odwołaniach wstecznych \nwe wzorcu i $nw łańcuchu zastępczym.

W innych odmianach wyrażeń regularnych (PCRE, Perl) można ich również używać w wywołaniach podprogramów .

Możesz uzyskać dostęp do tekstu dopasowanego do określonej grupy za pomocą Matcher.group(int group). Numery grup można zidentyfikować za pomocą powyższej zasady.

W niektórych odmianach wyrażeń regularnych (PCRE, Perl) dostępna jest funkcja resetowania gałęzi, która umożliwia użycie tej samej liczby do przechwytywania grup w różnych gałęziach naprzemienności .

Nazwa grupy

W języku Java 7 można zdefiniować nazwaną grupę przechwytywania (?<name>pattern) i uzyskać dostęp do dopasowanej treści Matcher.group(String name). Wyrażenie regularne jest dłuższe, ale kod jest bardziej znaczący, ponieważ wskazuje, co próbujesz dopasować lub wyodrębnić za pomocą wyrażenia regularnego.

Nazwy grup są używane w odwołaniach wstecznych \k<name>we wzorcu i ${name}w łańcuchu zastępczym.

Nazwane grupy przechwytywania są nadal numerowane za pomocą tego samego schematu numerowania, więc można do nich również uzyskać dostęp za pośrednictwem Matcher.group(int group).

Wewnętrznie implementacja Javy po prostu odwzorowuje nazwę na numer grupy. Dlatego nie możesz użyć tej samej nazwy dla 2 różnych grup przechwytywania.


1
ŁAŁ! Dziękuję @nhahtdh za wyjaśnienie grup nieprzechwytywanych, w jaki sposób działa kolejność zagnieżdżania. Byłem zaskoczony tym, jak działają numery grup, dopóki w końcu nie przeczytałem twojego wyjaśnienia. Wielkie dzięki!
MMeah

92

Dla reszty z nas

Oto prosty i jasny przykład tego, jak to działa

Regex: ([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

Strunowy: "!* UserName10 John Smith 01123 *!"

group(0): UserName10 John Smith 01123
group(1): UserName10
group(2):  
group(3): John Smith
group(4):  
group(5): 01123

Jak widać, utworzyłem PIĘĆ grup, z których każda jest umieszczona w nawiasach.

Dołączyłem! * I *! po obu stronach, aby było jaśniejsze. Zwróć uwagę, że żaden z tych znaków nie znajduje się w wyrażeniu regularnym i dlatego nie zostanie wyświetlony w wynikach. Grupa (0) podaje tylko cały pasujący ciąg (wszystkie moje kryteria wyszukiwania w jednym wierszu). Grupa 1 zatrzymuje się tuż przed pierwszą spacją, ponieważ znak spacji nie został uwzględniony w kryteriach wyszukiwania. Grupy 2 i 4 to po prostu spacja, która w tym przypadku jest dosłownie spacją, ale może być również tabulatorem lub wysuwem wiersza itp. Grupa 3 zawiera spację, ponieważ umieściłem ją w kryteriach wyszukiwania ... itd.

Mam nadzieję, że to ma sens.


1
doskonały przykład, który jest łatwy do zrozumienia dla początkujących. Wątpię, czy to to samo, co grupowanie reg ex w Pythonie? czy jest jakaś różnica? Jestem nowy w reg ex, dlatego jestem trochę zdezorientowany w obu językach.
Mani,

1
To nie jest poprawne wyrażenie regularne Java: ukośniki odwrotne należy podwoić.
Nicolas Raoul,

1
@NicolasRaoul: Podwójny lewy ukośnik wynika ze składni zmiany znaczenia w literale ciągu. Rzeczywista składnia wyrażenia regularnego (tj. Jeśli wypisujesz na konsoli łańcuch zawierający wyrażenie regularne) nie wymaga podwójnego odwrotnego ukośnika.
nhahtdh

@NicolasRaoul Jeśli miałbyś skopiować i wkleić mój ciąg wyrażenia regularnego do rzeczywistego kodu java przy użyciu odpowiedniego IDE, IDE odpowiednio sformatowałoby ukośniki ucieczki zgodnie z potrzebami. Ale mój Regex jest poprawny technicznie i składniowo, a jego głównym celem jest zademonstrowanie związku między kodem wyrażenia regularnego a uzyskanymi wynikami (na bardzo konkretnym przykładzie) ... trochę rozjaśnij ... ☺
Michael Sims

44

Nawiasy ()służą do grupowania wyrażeń regularnych.

group(1)Zawiera ciąg znaków, który jest między nawiasami (.*)więc .*w tym przypadku

I group(0)zawiera cały dopasowany ciąg.

Gdybyś miał więcej grup (czytaj (...)), zostałby podzielony na grupy z następnymi indeksami (2, 3 itd.).


2
Więc mam rację, że dodawanie nawiasów w rzeczywistości służy do tworzenia grup?
P basak

3
Tak, możemy to powiedzieć.
Michał Borek
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.