JavaRush /Blog Java /Random-PL /Wyrażenia regularne w Javie, część 3

Wyrażenia regularne w Javie, część 3

Opublikowano w grupie Random-PL
Przedstawiamy Państwu tłumaczenie krótkiego przewodnika po wyrażeniach regularnych w Javie, napisanego przez Jeffa Friesena dla serwisu javaworld . Dla ułatwienia czytania artykuł podzieliliśmy na kilka części. Wyrażenia regularne w Javie, część 3 - 1Wyrażenia regularne w Javie, część 1. Wyrażenia regularne w Javie, część 2

Uprość typowe zadania programistyczne za pomocą interfejsu API Regex

W częściach 1 i 2 tego artykułu zapoznałeś się z wyrażeniami regularnymi i interfejsem API Regex. Poznałeś klasę Patterni przejrzałeś przykłady demonstrujące konstrukcje wyrażeń regularnych, od prostego dopasowywania wzorców przy użyciu ciągów literałów po bardziej złożone dopasowywanie przy użyciu zakresów, elementów dopasowujących granice i kwantyfikatorów. W tej i kolejnych częściach rozważymy zagadnienia nie omówione w pierwszej części, przestudiujemy odpowiednie metody zajęć Patterni Matcher. PatternSyntaxExceptionPoznasz także dwa narzędzia, które korzystają z wyrażeń regularnych , aby ułatwić wykonywanie typowych problemów programistycznych. Pierwsza z nich wyodrębnia komentarze z kodu do dokumentacji. Druga to biblioteka kodu wielokrotnego użytku przeznaczona do przeprowadzania analizy leksykalnej - niezbędny element asemblerów, kompilatorów i podobnego oprogramowania.

POBIERZ KOD ŹRÓDŁOWY

Cały kod źródłowy (stworzony przez Jeffa Friesena dla JavaWorld) aplikacji demonstracyjnych opisanych w tym artykule można pobrać stąd .

Nauka API Regex

Patterni MatcherPatternSyntaxExceptiontrzema klasami tworzącymi interfejs API Regex. Każdy z nich udostępnia metody umożliwiające użycie wyrażeń regularnych w kodzie.

Metody klasy Pattern

Instancją klasy Patternjest skompilowane wyrażenie regularne, zwane także wzorcem. Wyrażenia regularne są kompilowane w celu poprawy wydajności operacji dopasowywania wzorców. Następujące metody statyczne obsługują kompilację.
  • Pattern compile(String regex)kompiluje zawartość regexw reprezentację pośrednią, która jest przechowywana w nowym pliku Pattern. Ta metoda albo zwraca odwołanie do obiektu, jeśli się powiedzie, albo zgłasza wyjątek, PatternSyntaxExceptionjeśli wykryta zostanie nieprawidłowa składnia wyrażenia regularnego. Każdy obiekt klasy Matcherużywany przez ten Patternobiekt lub zwracany przez ten obiekt używa ustawień domyślnych, takich jak wyszukiwanie z rozróżnianiem wielkości liter. Na przykład fragment kodu Pattern p = Pattern.compile("(?m)^\\."); tworzy obiekt Pattern, który przechowuje skompilowaną reprezentację wyrażenia regularnego w celu dopasowania ciągów znaków rozpoczynających się od znaku kropki.

  • Pattern compile(String regex, int flags)rozwiązuje ten sam problem co Pattern compile(String regex), ale biorąc pod uwagę flags: zestaw stałych bitowych dla flag bitowych typu OR. Klasa Patterndeklaruje stałe CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINES, które można łączyć za pomocą bitowego OR (na przykład CASE_INSENSITIVE | DOTALL) i przekazywać jako argument flags.

  • Z wyjątkiem CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS, te stałe stanowią alternatywę dla zagnieżdżonych wyrażeń flagowych przedstawionych w części 1. Jeśli napotkana zostanie stała flagowa inna niż zdefiniowana w klasie Pattern, metoda Pattern compile(String regex, int flags) zgłasza wyjątek java.lang.IllegalArgumentException. Na przykład Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);odpowiednik poprzedniego przykładu, w którym stała Pattern.MULTILINEi zagnieżdżone wyrażenie flagi (?m)robią to samo.
Czasami konieczne jest uzyskanie kopii oryginalnego ciągu wyrażenia regularnego wkompilowanego w obiekt Patternwraz z używanymi przez nie flagami. Aby to zrobić, możesz wywołać następujące metody:
  • String pattern()zwraca oryginalny ciąg wyrażenia regularnego skompilowany do pliku Pattern.

  • int flags()zwraca flagi obiektu Pattern.
Po otrzymaniu obiektu Patternzwykle wykorzystuje się go do uzyskania obiektu Matcherw celu wykonania operacji dopasowywania wzorców. Metoda Matcher matcher(Charsequence input)tworzy obiekt Matcher, który wyszukuje w tekście inputdopasowanie do wzorca obiektu Pattern. Po wywołaniu zwraca referencję do tego obiektu Matcher. Na przykład polecenie Matcher m = p.matcher(args[1]);zwraca Matcherobiekt, Patterndo którego odwołuje się zmienna p.
Jednorazowe wyszukiwanie
Metoda static boolean matches(String regex, CharSequence input)klasowa Patternpozwala zaoszczędzić na tworzeniu obiektów Patterni Matcherjednorazowym wyszukiwaniu według szablonu. Ta metoda zwraca wartość true, jeśli inputwzorzec jest dopasowany regex, w przeciwnym razie zwraca wartość false. Jeśli wyrażenie regularne zawiera błąd składniowy, metoda zgłasza wyjątek PatternSyntaxException. Na przykład System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));drukuje true, potwierdzając, że fraza all lowercase letters and whitespace onlyzawiera tylko spacje i małe litery.
Wyrażenia regularne w Javie, część 3 - 2

Dzielenie tekstu

Większość programistów przynajmniej raz napisała kod dzielący tekst wejściowy na części składowe, na przykład konwertując tekstowe konto pracownika na zestaw pól. Klasa Patternzapewnia możliwość wygodniejszego rozwiązania tego żmudnego zadania za pomocą dwóch metod podziału tekstu:
  • Metoda String[] split(CharSequence text, int limit)dokonuje podziału textwedług znalezionych dopasowań do wzorca obiektu Patterni zwraca wyniki w postaci tablicy. Każdy element tablicy określa sekwencję tekstu oddzieloną od następnej sekwencji fragmentem tekstu pasującym do wzorca (lub końcem tekstu). Elementy tablicy są w tej samej kolejności, w jakiej występują w text.

    W tej metodzie liczba elementów tablicy zależy od parametru limit, który również kontroluje liczbę znalezionych dopasowań.

    • Wartość dodatnia powoduje wyszukiwanie nie więcej niż limit-1dopasowań, a długość tablicy wynosi nie więcej niż limitelementy.
    • Jeśli wartość jest ujemna, przeszukiwane są wszystkie możliwe dopasowania, a długość tablicy może być dowolna.
    • Jeśli wartość wynosi zero, przeszukiwane są wszystkie możliwe dopasowania, długość tablicy może być dowolna, a puste linie na końcu są odrzucane.

  • Metoda String[] split(CharSequence text)wywołuje poprzednią metodę z 0 jako argumentem ograniczającym i zwraca wynik wywołania.
Poniżej znajdują się wyniki metody split(CharSequence text)rozwiązania problemu podziału konta pracownika na osobne pola imienia i nazwiska, wieku, adresu pocztowego i wynagrodzenia:
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
Powyższy kod opisuje wyrażenie regularne, które pozwala znaleźć znak przecinka, po którym następuje pojedynczy znak spacji. Oto efekty jego realizacji:
John Doe
47
Hillsboro Road
32000

Predykaty szablonów i interfejs API strumieni

W Javie 8 w klasie Patternpojawiła się metoda . Ta metoda tworzy predykat (funkcję z wartością logiczną), który służy do dopasowania wzorca. Zastosowanie tej metody pokazano w następującym fragmencie kodu: Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Ten kod tworzy listę nazw języków programowania, a następnie kompiluje wzorzec, aby znaleźć wszystkie nazwy zaczynające się na literę c. Ostatnia linia kodu powyżej implementuje odbieranie szeregowego strumienia danych z tą listą jako źródłem. Konfiguruje filtr za pomocą funkcji logicznej, asPredicate()która zwraca wartość true, gdy nazwa zaczyna się od litery, ci wykonuje iterację po strumieniu, wypisując pasujące nazwy na standardowe wyjście. Ta ostatnia linia jest odpowiednikiem następującej regularnej pętli, znanej z aplikacji RegexDemo z Części 1:
for (String progLang: progLangs)
   if (p.matcher(progLang).find())
      System.out.println(progLang);

Metody klasy Matcher

Instancja klasy Matcheropisuje mechanizm wykonywania operacji dopasowywania wzorców na sekwencji znaków poprzez interpretację skompilowanego wyrażenia regularnego klasy Pattern. Obiekty klasy Matcherobsługują różne rodzaje operacji wyszukiwania wzorców:
  • Metoda boolean find()przeszukuje tekst wejściowy pod kątem następnego dopasowania. Ta metoda rozpoczyna skanowanie od początku określonego tekstu lub od pierwszego znaku po poprzednim dopasowaniu. Druga opcja jest możliwa tylko wtedy, gdy poprzednie wywołanie tej metody zwróciło wartość true, a mechanizm rozpoznawania nazw nie został zresetowany. W każdym przypadku, jeśli wyszukiwanie zakończy się pomyślnie, zwracana jest wartość logiczna true. Przykład tej metody można znaleźć w RegexDemoCzęści 1.

  • Metoda boolean find(int start)resetuje moduł dopasowujący i przeszukuje tekst w poszukiwaniu następnego dopasowania. Przeglądanie rozpoczyna się od pozycji określonej parametrem start. Jeśli wyszukiwanie zakończy się pomyślnie, zwracana jest wartość logiczna true. Na przykład m.find(1);skanuje tekst zaczynając od pozycji 1(pozycja 0 jest ignorowana). Jeśli parametr startzawiera wartość ujemną lub wartość większą niż długość tekstu elementu dopasowującego, metoda zgłasza wyjątek java.lang.IndexOutOfBoundsException.

  • Metoda boolean matches()próbuje dopasować cały tekst do wzorca. Zwraca wartość logiczną true, jeśli cały tekst pasuje do wzorca. Na przykład kod Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());generuje wynik , falseponieważ znak !nie jest znakiem słownym.

  • Metoda boolean lookingAt()próbuje dopasować podany tekst do wzorca. Ta metoda zwraca wartość true, jeśli jakakolwiek część tekstu pasuje do wzorca. W przeciwieństwie do metody matches();, nie cały tekst musi pasować do wzorca. Na przykład Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());wyświetli true, ponieważ początek tekstu abc!składa się tylko ze znaków słowotwórczych.

W przeciwieństwie do obiektów klas Pattern, obiekty klas Matcherzachowują informacje o stanie. Czasami może być konieczne zresetowanie modułu dopasowującego, aby wyczyścić te informacje po zakończeniu wyszukiwania wzorców. Dostępne są następujące metody resetowania modułu rozpoznawania nazw:
  • Metoda Matcher reset()resetuje stan mechanizmu dopasowującego, łącznie z pozycją, która ma zostać dołączona na końcu (resetowana do 0). Następna operacja wyszukiwania wzorca rozpoczyna się na początku tekstu dopasowującego. Zwraca referencję do bieżącego obiektu Matcher. Na przykład m.reset();resetuje program rozpoznawania nazw, do którego odwołuje się m.

  • Metoda Matcher reset(CharSequence text)resetuje stan mechanizmu rozpoznawania nazw i ustawia nowy tekst mechanizmu rozpoznawania nazw na text. Następna operacja wyszukiwania wzorca rozpoczyna się na początku nowego tekstu dopasowującego. Zwraca referencję do bieżącego obiektu Matcher. Na przykład m.reset("new text");resetuje przywoływany program rozpoznawania nazw mi ustawia nowy tekst mechanizmu rozpoznawania nazw na "new text".

Wyrażenia regularne w Javie, część 3 - 3

Dodanie tekstu na końcu

Pozycja elementu dopasowującego, który ma zostać dodany na końcu, określa początek tekstu dopasowującego, który jest dodawany na końcu obiektu typu java.lang.StringBuffer. Następujące metody wykorzystują tę pozycję:
  • Metoda Matcher appendReplacement(StringBuffer sb, String replacement)odczytuje znaki tekstu dopasowującego i dołącza je na końcu obiektu, do którego StringBufferodwołuje się argument sb. Ta metoda zatrzymuje czytanie na ostatnim znaku poprzedzającym poprzednie dopasowanie wzorca. Następnie metoda dołącza znaki z obiektu typu, do Stringktórego odwołuje się argument, replacementna koniec obiektu StringBuffer(łańcuch może zawierać odniesienia do ciągów tekstowych przechwyconych podczas poprzedniego wyszukiwania; są one określane na podstawie przechwytywanych replacementznaków i numerów grup). ($)Na koniec metoda ustawia wartość pozycji elementu dopasowującego, która ma zostać dołączona do pozycji ostatniego dopasowanego znaku plus jeden, a następnie zwraca odwołanie do bieżącego elementu dopasowującego.

  • Metoda Matcher appendReplacement(StringBuffer sb, String replacement)zgłasza wyjątek java.lang.IllegalStateException, jeśli moduł dopasowujący nie znalazł jeszcze dopasowania lub poprzednia próba wyszukiwania nie powiodła się. Zgłasza wyjątek, IndexOutOfBoundsExceptionjeśli linia replacementokreśla grupę przechwytywania, której nie ma we wzorcu).

  • Metoda StringBuffer appendTail(StringBuffer sb)dodaje cały tekst do obiektu StringBufferi zwraca odwołanie do tego obiektu. Po ostatnim wywołaniu metody appendReplacement(StringBuffer sb, String replacement)wywołaj metodę, appendTail(StringBuffer sb)aby skopiować pozostały tekst do obiektu StringBuffer.

Przechwycone grupy
Jak pamiętasz z części 1, grupa przechwytywania to sekwencja znaków ujęta w nawiasy ( ()) metaznaki. Celem tej konstrukcji jest przechowywanie znalezionych znaków do późniejszego ponownego wykorzystania podczas dopasowywania wzorców. Podczas wyszukiwania wzorców wszystkie znaki z przechwyconej grupy są traktowane jako jedna całość.
Poniższy kod wywołuje metody appendReplacement(StringBuffer sb, String replacement)i appendTail(StringBuffer sbw celu zamiany wszystkich wystąpień sekwencji znaków w tekście źródłowym catna caterpillar:
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
Użycie przechwyconej grupy i odniesienia do niej w tekście zastępczym nakazuje programowi wstawienie erpillarpo każdym wystąpieniu cat. Wynik wykonania tego kodu wygląda następująco: one caterpillar, two caterpillars, or three caterpillars on a fence

Zastępowanie tekstu

Klasa Matcherudostępnia nam dwie metody zastępowania tekstu, uzupełniające metodę appendReplacement(StringBuffer sb, String replacement). Korzystając z tych metod, możesz zastąpić pierwsze wystąpienie [zastąpionego tekstu] lub wszystkie wystąpienia:
  • Metoda String replaceFirst(String replacement)resetuje mechanizm dopasowujący, tworzy nowy obiekt String, kopiuje wszystkie znaki tekstu dopasowującego (aż do pierwszego dopasowania) do tego ciągu, dołącza znaki od jego końca replacement, kopiuje pozostałe znaki do ciągu i zwraca obiekt String(ciąg replacementmoże zawierać odniesienia do tych przechwyconych podczas poprzednich sekwencji tekstu wyszukiwania przy użyciu symboli dolara i przechwyconych numerów grup).

  • Metoda String replaceAll(String replacement)działa podobnie jak metoda String replaceFirst(String replacement), z tą różnicą, że wszystkie znalezione dopasowania zastępuje replacementznakami z ciągu znaków.

Wyrażenie regularne \s+wyszukuje jeden lub więcej białych znaków w tekście wejściowym. Poniżej użyjemy tego wyrażenia regularnego i wywołamy metodę replaceAll(String replacement)usuwania zduplikowanych spacji:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
Oto wyniki: Удаляем лишние пробелы. Wyrażenia regularne w Javie, część 4 Wyrażenia regularne w Javie, część 5
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION