W jaki sposób grupy nie przechwytujące, tj. Są (?:)
używane w wyrażeniach regularnych i do czego służą?
regex
capturing-group
regex-group
never_had_a_name
źródło
źródło
Odpowiedzi:
Pozwól, że wyjaśnię to przykładem.
Rozważ następujący tekst:
Teraz, jeśli zastosuję nad nim regex ...
... uzyskałbym następujący wynik:
Ale nie dbam o protokół - chcę tylko hosta i ścieżkę do adresu URL. Tak więc zmieniam wyrażenie regularne, aby uwzględnić grupę nie przechwytującą
(?:)
.Teraz mój wynik wygląda następująco:
Widzieć? Pierwsza grupa nie została schwytana. Analizator składni używa go do dopasowania tekstu, ale w wyniku końcowym ignoruje go później.
EDYTOWAĆ:
Zgodnie z życzeniem pozwól mi też wyjaśnić grupy.
Grupy służą wielu celom. Mogą pomóc ci wyodrębnić dokładne informacje z większego dopasowania (które można również nazwać), pozwalają przeszukać poprzednią dopasowaną grupę i mogą być użyte do zastąpienia. Spróbujmy kilku przykładów, prawda?
Wyobraź sobie, że masz jakiś XML lub HTML (pamiętaj, że regex może nie być najlepszym narzędziem do tego zadania , ale jest to dobry przykład). Chcesz przeanalizować tagi, abyś mógł zrobić coś takiego (dodałem spacje, aby ułatwić zrozumienie):
Pierwszy regex ma nazwaną grupę (TAG), podczas gdy drugi używa wspólnej grupy. Oba wyrażenia regularne robią to samo: używają wartości z pierwszej grupy (nazwy znacznika), aby dopasować znacznik zamykający. Różnica polega na tym, że pierwszy używa nazwy, aby dopasować wartość, a drugi używa indeksu grupy (który zaczyna się od 1).
Spróbujmy teraz podstawić. Rozważ następujący tekst:
Teraz użyjmy tego głupiego wyrażenia regularnego:
Ten wyrażenie regularne dopasowuje słowa zawierające co najmniej 3 znaki i używa grup do oddzielenia pierwszych trzech liter. Rezultat jest następujący:
Jeśli zastosujemy łańcuch podstawienia:
... staramy się użyć pierwszej grupy, dodać podkreślenie, użyć trzeciej grupy, potem drugiej grupy, dodać kolejny podkreślenie, a następnie czwartej grupy. Powstały ciąg będzie podobny do poniższego.
Możesz także używać nazwanych grup do podstawienia, używając
${name}
.Aby pobawić się wyrażeniami regularnymi , polecam http://regex101.com/ , która zawiera sporo szczegółów na temat działania wyrażeń regularnych; oferuje również kilka silników regex do wyboru.
źródło
Możesz użyć grup przechwytywania, aby zorganizować i przeanalizować wyrażenie. Grupa, która nie zdobywa, ma pierwszą korzyść, ale nie ma narzutu drugiej. Nadal możesz powiedzieć, że grupa, która nie przechwytuje, jest na przykład opcjonalna.
Powiedzmy, że chcesz dopasować tekst numeryczny, ale niektóre liczby można zapisać jako 1., 2., 3., 4., ... Jeśli chcesz przechwycić część liczbową, ale nie sufiks (opcjonalny), możesz użyć grupy, która nie jest przechwytywana .
To będzie pasowało do liczb w postaci 1, 2, 3 ... lub w postaci 1, 2, 3, ... ale przechwyci tylko część numeryczną.
źródło
?:
jest używany, gdy chcesz pogrupować wyrażenie, ale nie chcesz zapisać go jako dopasowanej / przechwyconej części łańcucha.Przykładem może być coś pasującego do adresu IP:
Zauważ, że nie obchodzi mnie zapisywanie pierwszych 3 oktetów, ale
(?:...)
grupowanie pozwala mi skrócić wyrażenie regularne bez ponoszenia kosztów przechwytywania i przechowywania dopasowania.źródło
Sprawia, że grupa nie jest przechwytywana, co oznacza, że podciąg pasujący do tej grupy nie zostanie uwzględniony na liście przechwyceń. Przykład w rubinie ilustrujący różnicę:
źródło
(?:)
nie produkuje przechwytywania, a nie zademonstrować przydatny przykład(?:)
.(?:)
jest przydatny, gdy chcesz pogrupować podwyrażenie (powiedz, kiedy chcesz zastosować kwantyfikatory do nie-atomowego podwyrażenia lub jeśli chcesz ograniczyć zakres a|
), ale nie chcesz niczego wychwytywać.MOTYWACJA HISTORYCZNA:
Istnienie grup nie przechwytujących można wyjaśnić za pomocą nawiasów.
Rozważ wyrażenia,
(a|b)c
aa|bc
ze względu na pierwszeństwo konkatenacji|
wyrażenia te reprezentują dwa różne języki ({ac, bc}
i{a, bc}
odpowiednio).Jednak nawiasy są również używane jako grupa pasująca (jak wyjaśniono w innych odpowiedziach ...).
Jeśli chcesz mieć nawias, ale nie przechwytujesz podwyrażenia, korzystasz z GRUP NIEDOJMUJĄCYCH. W przykładzie
(?:a|b)c
źródło
Pozwól mi spróbować z przykładem:
Kod Regex:
(?:animal)(?:=)(\w+)(,)\1\2
Szukana fraza:
Linia 1 -
animal=cat,dog,cat,tiger,dog
Linia 2 -
animal=cat,cat,dog,dog,tiger
Linia 3 -
animal=dog,dog,cat,cat,tiger
(?:animal)
-> Nie przechwycona grupa 1(?:=)
-> Nie przechwycona grupa 2(\w+)
-> Przechwycona grupa 1(,)
-> Captured Group 2\1
-> wynik złapanej grupy 1, tj. w linii 1 jest kot, w linii 2 jest kot, w linii 3 jest pies.\2
-> wynik przechwyconej grupy 2, tj. przecinek (,)Tak więc w tym kodzie, podając,
\1
a następnie\2
przypominamy lub powtarzamy wynik przechwyconych grup 1 i 2 odpowiednio później w kodzie.Zgodnie z kolejnością kodu
(?:animal)
powinna być grupa 1 i(?:=)
powinna być grupa 2 i trwa nadal.ale podając
?:
znak „sprawiamy, że grupa dopasowań nie jest przechwytywana (które nie liczą się w dopasowanej grupie, więc numer grupy zaczyna się od pierwszej przechwyconej grupy, a nie nie przechwyconej”), tak aby powtórzenie wyniku grupy dopasowań(?:animal)
nie można wywołać później w kodzie.Mam nadzieję, że to wyjaśnia użycie grupy nieprzechwyconej.
źródło
Grupy, które przechwytują , możesz użyć później w wyrażeniu regularnym w celu dopasowania LUB możesz użyć ich w zastępczej części wyrażenia regularnego. Utworzenie grupy nie przechwytującej po prostu zwalnia tę grupę z użycia z jednego z tych powodów.
Grupy nie przechwytujące są świetne, jeśli próbujesz uchwycić wiele różnych rzeczy, a istnieją grupy, których nie chcesz przechwytywać.
To właściwie powód ich istnienia. Podczas gdy uczysz się o grupach, poznajesz grupy atomowe , robią dużo! Istnieją również grupy opisowe, ale są one nieco bardziej złożone i nie są tak często używane.
Przykład użycia później w wyrażeniu regularnym (odwołanie wsteczne):
<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>
[Znajduje znacznik xml (bez wsparcia ns)]([A-Z][A-Z0-9]*)
jest grupą przechwytującą (w tym przypadku jest to zmienna)Później w wyrażeniu regularnym
\1
oznacza, że będzie pasował tylko do tego samego tekstu, który był w pierwszej grupie (([A-Z][A-Z0-9]*)
grupie) (w tym przypadku pasuje do znacznika końcowego).źródło
Cóż, jestem programistą JavaScript i postaram się wyjaśnić jego znaczenie dla JavaScript.
Rozważ scenariusz, w którym chcesz dopasować,
cat is animal
kiedy chcesz dopasować kota i zwierzę, i oba powinny miećis
między nimi przerwę.źródło
W skomplikowanych wyrażeniach regularnych może wystąpić sytuacja, w której chcesz użyć dużej liczby grup, z których niektóre służą do dopasowywania powtórzeń, a niektóre z nich służą do dostarczania referencji wstecznych. Domyślnie tekst pasujący do każdej grupy jest ładowany do tablicy odwołań wstecznych. Tam, gdzie mamy wiele grup i musimy mieć możliwość odwoływania się do niektórych z nich z tablicy odwołań wstecznych, możemy zastąpić to domyślne zachowanie, aby powiedzieć wyrażeniu regularnemu, że niektóre grupy istnieją tylko w celu obsługi powtarzania i nie muszą być przechwytywane i przechowywane w tablicy odwołań wstecznych.
źródło
Nie mogę komentować najważniejszych odpowiedzi, aby powiedzieć: chciałbym dodać wyraźny punkt, który jest sugerowany tylko w najlepszych odpowiedziach:
Grupa non-przechwytywanie
(?...)
ma nie usuwać żadnych znaków z oryginalnego pełnego meczu, tylko to reorganizuje regex wizualnie do programatora.Aby uzyskać dostęp do określonej części wyrażenia regularnego bez zdefiniowanych obcych znaków, zawsze będziesz musiał użyć
.group(<index>)
źródło
tl; dr grupy nie przechwytujące, jak sama nazwa wskazuje, to fragmenty wyrażenia regularnego, których nie chcesz uwzględniać w dopasowaniu, i
?:
jest to sposób na zdefiniowanie grupy jako nie przechwytującej.Załóżmy, że masz adres e-mail
[email protected]
. Poniższe wyrażenie regularne utworzy dwie grupy , część id i część @ example.com.(\p{Alpha}*[a-z])(@example.com)
. Dla uproszczenia wyodrębniamy całą nazwę domeny wraz z@
postacią.Powiedzmy, że potrzebujesz tylko części identyfikatora adresu. To, co chcesz zrobić, to pobrać pierwszą grupę wyniku dopasowania, otoczoną
()
wyrażeniem regularnym, a sposobem na to jest użycie składni grupy nieprzechwycącej, tj?:
. Tak więc wyrażenie regularne(\p{Alpha}*[a-z])(?:@example.com)
zwróci tylko część id wiadomości e-mail.źródło
Jedną interesującą rzeczą, na którą się natknąłem, jest fakt, że możesz mieć grupę przechwytującą wewnątrz grupy, która nie jest przechwytująca. Spójrz na wyrażenie regularne dla pasujących adresów URL:
Wpisz ciąg adresu URL:
Pierwsza grupa w moim wyrażeniu regularnym
(?:([A-Za-z]+):)
to grupa nie przechwytująca, która jest zgodna ze schematem protokołu i:
znakiem dwukropka, tj.http:
Ale kiedy działałam poniżej kodu, widziałam, że pierwszy indeks zwróconej tablicy zawierał łańcuch,http
gdy myślałem o tymhttp
i dwukropek:
oba nie zostaną zgłoszone, ponieważ znajdują się w grupie, która nie została przechwycona.Pomyślałem, że jeśli pierwsza grupa nie
(?:([A-Za-z]+):)
jest grupą przechwytującą, to dlaczego zwracahttp
ciąg znaków w tablicy wyjściowej.Więc jeśli zauważysz, że w grupie
([A-Za-z]+)
nie przechwytywanej jest zagnieżdżona grupa. Ta zagnieżdżona grupa([A-Za-z]+)
jest grupą przechwytującą (która nie ma?:
na początku) w sobie w grupie nie przechwytującej(?:([A-Za-z]+):)
. Dlatego tekst jesthttp
nadal przechwytywany, ale:
znak dwukropka, który znajduje się w grupie, która nie została przechwycona, ale poza grupą przechwytującą, nie jest raportowany w tablicy wyjściowej.źródło
Otwórz narzędzia Google Chrome devTools, a następnie kartę Konsola: i wpisz:
Uruchom go, a zobaczysz:
Silnik
JavaScript
RegExp przechwytuje trzy grupy, elementy o indeksach 1,2,3. Teraz użyj znaku nie przechwytywania, aby zobaczyć wynik.Wynik to:
Jest to oczywiste, co nie jest grupą przechwytującą.
źródło
Myślę, że dałbym ci odpowiedź. Nie używaj zmiennych przechwytywania bez sprawdzenia, czy dopasowanie się powiodło.
Zmienne przechwytywania
$1
itp. Są niepoprawne, chyba że dopasowanie się powiedzie, a także nie zostaną wyczyszczone.W powyższym przykładzie, aby uniknąć przechwytywania bronto
$1
,(?:)
używany.Jeśli wzór jest dopasowany, to
$1
jest przechwytywany jako następny zgrupowany wzór.Wynik będzie następujący:
Jest to przydatne, jeśli nie chcesz, aby mecze były zapisywane.
źródło
Jest to niezwykle proste, możemy zrozumieć na podstawie prostego przykładu daty, załóżmy, że data jest wymieniona na 1 stycznia 2019 r. Lub 2 maja 2019 r. Lub na inną datę i po prostu chcemy ją przekonwertować na dd / mm / rrrr format , nie potrzebowalibyśmy miesiąca w tym przypadku jest to styczeń lub luty, więc aby uchwycić część liczbową, ale nie (opcjonalny) sufiks, możesz użyć grupy nie przechwytującej.
więc wyrażenie regularne brzmiałoby
To takie proste.
źródło