Kontynuujmy naukę wyrażeń regularnych. W tym artykule przyjrzymy się predefiniowanym klasom znaków oraz kwantyfikacji (wyszukiwaniu sekwencji).
Predefiniowane klasy znaków
Interfejs API klasPattern
zawiera predefiniowane klasy znaków, które oferują wygodne skróty do często używanych wyrażeń regularnych. W tej tabeli konstrukcje w lewej kolumnie są skróconymi reprezentacjami wyrażeń w prawej kolumnie. Na przykład \d
oznacza cyfrę (0-9), \w
oznacza dowolną wielką lub małą literę, podkreślenie lub cyfrę). Jeśli to możliwe, używaj predefiniowanych klas znaków. Dzięki temu Twój kod będzie łatwiejszy do odczytania i naprawienia błędów. Konstrukcje zaczynające się od ukośnika odwrotnego nazywane są znakami ucieczki lub chronionymi. W poprzednich artykułach mówiliśmy już o uciekaniu od znaków specjalnych za pomocą ukośników odwrotnych lub symboli \Q
i \E
używaniu ich jako zwykłych znaków. Jeśli używasz ukośnika odwrotnego ze zwykłymi znakami (literałami), musisz uciec przed ukośnikiem odwrotnym, aby wyrażenie się skompilowało.
private final String REGEX = "\\d"; // цифра
W tym przykładzie \d
wyrażenie regularne; dodatkowy ukośnik odwrotny jest niezbędny do skompilowania programu. Nasz program testowy odczytuje wyrażenia regularne bezpośrednio z konsoli, więc nie jest potrzebny żaden dodatkowy ukośnik. Poniższy przykład ilustruje użycie predefiniowanych klas znaków: W pierwszych trzech przykładach wyrażeniem regularnym jest po prostu „ .
” (znak specjalny kropki), co oznacza dowolny znak. Dlatego poszukiwania zakończyły się sukcesem we wszystkich przypadkach. Inne przykłady wykorzystują predefiniowane klasy znaków, których znaczenie omówiliśmy w powyższej tabeli.
Kwantyfikatory
Kwantyfikatory pozwalają określić liczbę wystąpień znaku w ciągu. Przyjrzyjmy się bliżej zawiłościom działania kwantyfikatorów zachłannych, leniwych i bardzo zachłannych. Na pierwszy rzut oka może się wydawać, że kwantyfikatory X?, X?? i X?+ działają w ten sam sposób: „X jest obecny raz lub wcale”. Istnieją niewielkie różnice w implementacji tych kwantyfikatorów, którym przyjrzymy się poniżej.Dopasowania o zerowej długości
Zacznijmy od chciwego. Zapiszmy trzy różne wyrażenia regularne: literę „a” ze znakami specjalnymi ?, * lub +. Zobaczmy, co się stanie, jeśli przetestujemy te wyrażenia regularne w pustej linii: W powyższym przykładzie wyszukiwanie zakończyło się sukcesem w pierwszych dwóch przypadkach, ponieważ wyrażenia a? i a* pozwalają na brak znaku a w ciągu. Należy również pamiętać, że indeks rozpoczęcia i ostatniego dopasowania są takie same (0). Ponieważ ciąg wejściowy nie ma długości, program nie znajduje niczego :) na pierwszej pozycji. Ten przypadek nazywa się dopasowaniem o zerowej długości. Takie dopasowania mają miejsce w kilku przypadkach: gdy linia wejściowa jest pusta, na początku linii wejściowej, po ostatnim znaku linii lub pomiędzy znakami w linii. Dopasowania o zerowej długości są łatwe do wykrycia: zaczynają się i kończą w tej samej pozycji. Przyjrzyjmy się jeszcze kilku przykładom dopasowań o zerowej długości. Przyjrzyjmy się dopasowaniom o zerowej długości na kilku kolejnych przykładach. Zmieńmy ciąg wejściowy na znak „a” i zaobserwujmy ciekawy efekt: wszystkie trzy kwantyfikatory znalazły znak „a”, ale pierwsze dwa, które uwzględniają brak znaku, znalazły dopasowanie o zerowej długości na pozycji 1 - po ostatnim znaku ciągu. Dzieje się tak, ponieważ program traktuje znak „a” jako ciąg znaków i „przegląda” go, aż nie będzie już żadnych dopasowań. W zależności od użytego kwantyfikatora program znajdzie lub nie znajdzie „nic” na końcu łańcucha. Zmieńmy teraz ciąg wejściowy na ciąg pięciu liter „a”: Wyrażenie regularne a? znajduje dopasowanie dla każdej litery w ciągu oddzielnie. Wyrażenie a* znajduje dwa dopasowania: sekwencję znaków „a” i dopasowanie o zerowej długości na pozycji 5. I wreszcie wyrażenie regularne a+ wyszukuje tylko ciąg znaków „a”, nie znajdując „nic” :) Co się stanie, jeśli na wejściu zostanie podany ciąg znaków zawierający różne znaki? Na przykład „ababaaaab”: Znak „b” znajduje się na pozycjach 1, 3 i 8, a program znajduje na tych pozycjach dopasowania o zerowej długości. Wyrażenie regularne a? nie zwraca uwagi na „b”, ale po prostu szuka obecności (lub nieobecności) znaku „a”. Jeśli kwantyfikator dopuszcza brak „a”, wszystkie znaki w ciągu inne niż „a” zostaną pokazane jako dopasowanie o zerowej długości. Aby znaleźć ciągi o określonej długości, po prostu określ długość w nawiasach klamrowych: Wyrażenie regularne a{3} wyszukuje ciąg trzech znaków „a”. Nic nie zostało znalezione w pierwszym wierszu, ponieważ nie było wystarczającej liczby „a” w wierszu. Drugi zawiera 3 znaki, które program znajdzie. Trzeci test również znajduje dopasowanie na początku ciągu. Wszystko po trzecim znaku nie spełnia wyrażenia regularnego, w poniższym kodzie tak jest i będzie kilka dopasowań: Aby określić minimalną długość sekwencji, użyj:Enter your regex: a{3,}
Enter input string to search: aaaaaaaaa
I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.
W tym przykładzie program znajduje tylko jedno dopasowanie, ponieważ ciąg spełnia wymagania dotyczące minimalnej długości sekwencji wynoszącej (3) znaki „a”. Na koniec ustawienie maksymalnej długości sekwencji: W tym przykładzie pierwsze dopasowanie zakończyło się na szóstym znaku. Drugie dopasowanie zawiera znaki występujące po szóstym, ponieważ spełniają wymagania dotyczące minimalnej długości. Jeśli ciąg znaków byłby o jeden znak krótszy, drugie dopasowanie nie byłoby możliwe.
GO TO FULL VERSION