Regex: grupy przechwytujące i odwołania wsteczne
Po tej lekcji wiesz, jak grupa zapamiętuje dopasowany tekst i jak odwołanie wsteczne wstawia go ponownie do wzorca. Dzięki temu wzorzec znajdzie powtórzenia.
W jednej minucie
Podwyrażenie to fragment wzorca ujęty w nawiasy, do którego dopasowania można się później odwołać.1
Nawiasy nie tylko grupują. Tekst, który dopasowały, możesz wstawić dalej we wzorcu jako \1, \2 i tak dalej.
Grupy numerujesz po lewych nawiasach, od lewej do prawej.1
Grupa zapamiętuje dopasowany tekst
W poprzedniej lekcji nawiasy ograniczały zasięg alternatywy. Teraz zapamiętują też, co dopasowały. Sam wzorzec w nawiasach pasuje tak samo jak bez nich.1
Odwołanie wsteczne to zapis \n, który dopasowuje ten sam tekst, co n-te podwyrażenie wcześniej we wzorcu.1
- \(ab\)dopasuj i zapamiętaj
- \1wstaw to samo
- ababcały tekst
printf 'abab\nabba\nab\n' | grep '\(ab\)\1'
# wypisze tylko abab
Wzorzec \(ab\)\1 znaczy: ab, a zaraz po nim to samo, co dopasowała grupa. Przy stałym tekście wynik jest taki sam jak dla abab. Różnica pojawia się, gdy grupa może pasować do wielu tekstów, jak w kolejnych przykładach.
Numeracja grup
Pierwszy lewy nawias to grupa 1, drugi to grupa 2.1 Odwołanie \2 wstawia więc tekst z drugiej grupy.
| Zapis | Wstawia tekst z |
|---|---|
\1 | pierwszego \( od lewej |
\2 | drugiego \( od lewej |
Przykład: \(a\)\(b\)\2\1 pasuje do abba.
printf 'abba\nabab\n' | grep -x '\(a\)\(b\)\2\1'
# wypisze abba: a, b, potem 2 = b, potem 1 = a
Dwa takie same fragmenty obok siebie
Odwołanie wsteczne pozwala zapisać coś, czego nie wyraziłyby wcześniejsze operatory: „tekst powtórzony dwa razy”.
Wzorzec ^\(.*\)\1$ pasuje do tekstów złożonych z dwóch sąsiadujących kopii tego samego fragmentu.1
| Tekst | Wynik | Dlaczego |
|---|---|---|
| abcabc | pasuje | abc dwa razy |
| aa | pasuje | a dwa razy |
| abcabd | nie pasuje | drugi fragment inny |
Wyniki sprawdziliśmy poleceniem grep -x w wersji 3.11.
printf 'to to jest\nto jest\nala la\n' | grep '\([a-z][a-z]*\) \1'
# wypisze: to to jest oraz ala la
Wzorzec z poprzedniego przykładu łapie też ala la, bo la la jest w środku większego słowa. Nie dopasowuje granic słów.
Gdy grupa powtarza się kilka razy
Powtórzona grupa zapamiętuje tylko ostatnie dopasowanie.1
printf 'abb\naba\n' | grep -x '\([ab]\)*\1'
# wypisze abb
W abb grupa dopasowuje najpierw a, potem b. Ostatnie dopasowanie to b, a \1 wymaga jeszcze jednego b. W aba ostatnia litera jest inna, więc wzorzec nie pasuje.
Częste błędy
Trzy pomyłki zdarzają się najczęściej przy grupach i odwołaniach.
| Błąd | Skutek | Poprawka |
|---|---|---|
\2 przy jednej grupie | grep zgłasza błąd | Sprawdź numerację lewych nawiasów |
(ab) zamiast \(ab\) w BRE | nawiasy dosłowne | Dodaj ukośniki albo użyj -E |
| odwołanie bez granic słów | fałszywe trafienia | Dodaj kotwice lub ogranicz wzorzec |
Kolumna „Poprawka” to nasza rekomendacja, nie cytat ze specyfikacji. Pierwsze dwa wiersze sprawdziliśmy w GNU grep 3.11.
Wzorzec jest niepoprawny, gdy przed \n stoi mniej niż n podwyrażeń.1
Pytania sprawdzające
Czym różni się \(ab\)\1 od abab?
Na tym przykładzie wynik jest ten sam. Ale \1 zawsze powtarza dokładnie ten tekst, który dopasowała grupa, także gdy jej wzorzec może pasować do wielu tekstów.
Do czego pasuje \(a\)\(b\)\2\1?
Do tekstu abba: najpierw a i b, potem tekst z grupy 2 (b), na końcu z grupy 1 (a).
Dlaczego ^\(.*\)\1$ pasuje do abcabc, ale nie do abcabd?
Grupa zapamiętuje abc, a \1 wymaga takiego samego tekstu zaraz potem. W abcabd drugi fragment jest inny.
Co zapamięta grupa powtórzona gwiazdką?
Tylko ostatnie dopasowanie. Odwołanie wsteczne wstawia ten ostatni fragment.
Podsumowanie
- Podwyrażenie to fragment wzorca w nawiasach; w BRE zapisujesz je jako
\(i\). - Odwołanie wsteczne
\ndopasowuje ten sam tekst, co n-te podwyrażenie. - Grupy numeruje się po lewych nawiasach, od lewej do prawej.
- Dzięki odwołaniom wzorzec może znaleźć powtórzony fragment.
- Powtórzona grupa zapamiętuje tylko ostatnie dopasowanie.
- Odwołanie do grupy, której nie ma, jest błędem.
Źródła
- Regular Expressions — The Open Group (POSIX.1-2017)sprawdzone 2026-11-03