Wyrażenia regularne
Wyrażenia regularne stanowią doskonały sposób na badanie i modyfikowanie tekstu. Dzięki swej olbrzymiej elastyczności pozwalają w łatwy sposób pobierać pasujące fragmenty tekstu. To tyle książkowej teorii.
A czym są wzorce w praktyce? Powiedzmy, że mamy fragment tekstu, w którym znajdują się jakieś kody pocztowe. Kod taki składa się z dwóch cyfr, myślnika, po którym występują trzy cyfry. Jeżeli chcielibyśmy znaleźć w takim tekście wszystkie kody, nie moglibyśmy użyć znanych nam już indexOf() czy includes(), ponieważ nie znamy konkretnej wartości. Znamy wzorzec.
Wyrażenia regularne nie sa domeną Javascriptu. Gdy nauczymy się ich - nawet w podstawowej formie - bardzo ułatwią nam codzienną prace z kodem. Za ich pomocą możemy dla przykładu w każdym porządnym edytorze zamieniać podobne wystąpienia tekstu (np. klasy, daty itp), masowo zmieniać nazwy plików itp. Poniżej przykład takiej zamiany:
Pisanie podstawowych wzorów wyrażeń nie jest jakieś bardzo skomplikowane. Problem pojawia się przy tych bardziej rozbudowanych. Tutaj częstokroć trzeba korzystać z Google szukając frazy "fraza test regexp" i posiłkować się poradami ze Stack Overflow.
Bardzo też przydają się tutaj narzędzia takie jak: https://regex101.com/, czy http://regexr.com/.
Na koniec warto też zerknąć na stronkę https://regexlearn.com, która interaktywnie uczy pisać takie wyrażenia.
Wyrażenia w Javascript
Aby w JavaScript korzystać z wyrażeń regularnych, możemy posłużyć się skróconym zapisem /wzor/ lub użyć konstruktora RegExp(wzór, flagi*), który przyjmuje 2 argumenty: wzór, którym będziemy testować, oraz dodatkowe flagi, które poznamy poniżej.
const reg = /pani?/gi
//lub za pomocą konstruktora
const reg = new RegExp("pani?" , "gi")Gdy już stworzymy wzór, musimy go użyć wraz z jedną z dostępnych metod. Je omówimy sobie w kolejnym rozdziale. W poniższych przykładach będe korzystał głównie z metody test(), która zwraca prawdę lub fałsz.
const reg = /[0-9]{3}/
console.log(reg.test("Ala")) //false
console.log(reg.test("102")) //true "102"
console.log(reg.test("Ala 007")) //true "Ala 007"
console.log(reg.test("Numer czołgu miał numer 102 bo tak")) //true "Numer czołgu miał numer 102 bo tak"Flagi czyli dodatkowe opcje dla wyrażeń
Dla każdego wyrażenia regularnego możemy ustawić dodatkowe flagi (opcje), które zmieniają jego działanie:
Przy skróconej składni flagi umieszczamy za wyrażeniem regularnym. Dla obiektu RegExp umieszczamy je jako drugi parametr:
i
powoduje niebranie pod uwagę wielkości liter
g
powoduje zwracanie wszystkich pasujących fragmentów, a nie tylko pierwszego
m
powoduje wyszukiwanie w tekście kilku liniowym. W trybie tym znak początku i końca wzorca (^$) jest wstawiany dla każdej linii z osobna.
s
Sprawia, że znak . pasuje także do znaku nowe linii (\n)
u
Włącza możliwość używania kodów dla znaków unicode
y
Włącza tryb sticky. Kolejne wyszukiwania będą rozpoczynać się od pozycji ostatniego szukania, którą definiuje lastIndex
Pozycja w tekście
Domyślnie szukany fragment może znajdować się w dowolnym miejscu.
^
Znak ^ oznacza, że szukany fragment musi znajdować się na początku badanego tekstu
$
Znak $ oznacza, że szukany fragment musi znajdować się na końcu badanego tekstu
Jeżeli chcemy sprawdzić, czy dany fragment występuje na końcu linii wiele liniowego tekstu, powinniśmy dodać do wyrażenia flagę m
Ilości znaków
*
Znak * oznacza 0 lub więcej wystąpień poprzedzającej grupy lub znaku.
+
Znak + oznacza 1 lub więcej wystąpień poprzedzającego znaku lub grupy.
{}
Wewnątrz klamer podajemy liczbę znaków. Możemy tutaj podać konkretną wartość {4}, minimalną {4,}, maksymalną {,4} lub zakres znaków {2,4}:
?
Znak ? oznacza 0 lub 1 wystąpienie poprzedzającego znaku lub grupy.
Użycie znaku ? za znakami ., + lub {} sprawia, że wyszukiwanie przechodzi w tryb wyszukiwania niezachłannego. Oznacza to, że pasujący ciąg skończy się na najmniejszym pasującym fragmencie, a nie największym
Zbiory znaków
[...]
Między nawiasy kwadratowe możemy wstawić znaki, które będą stanowić zbiór, który weźmie udział w teście
Podając zbiory znaków możemy określać ich zakresy:
Zbiory znaków możemy też negować za pomocą znaku ^:
Możemy też skorzystać z przygotowanych dla nas grup znaków:
\d
każdy znak będący cyfrą. Równoznaczne z [0-9]
\D
każdy znak nie będący cyfrą. Równoznaczne z [^0-9]
\w
każdy znak będący literą, cyfrą i znakiem _. Równoznaczne z [a-zA-Z0-9_]
\W
każdy znak nie będący literą, cyfrą i znakiem _. Równoznaczne z [^a-zA-Z0-9_]
\s
znak spacji, tabulacji lub nowego wiersza
\S
każdy znak nie będący spacją, tabulacją lub znakiem nowego wiersza
\n
znak nowego wiersza
\t
znak tabulacji
\uXXXX
oznacza znak o danym kodzie Unicode. Do użycia wymaga odpowiedniej flagi
.
oznacza dowolny znak nie będący znakiem nowej linii. Żeby oznaczał też nową linię musimy użyć odpowiedniej flagi.
Dodatkowo mamy tutaj specjalne oznaczenie \b, które oznacza granicę słowa.
Możemy go użyć w trzech kluczowych miejscach:
na początku słowa, od którego zaczynają się znaki
\wna końcu słowa przed którym są znaki
\ww środku słowa gdzie po obu stronach są znaki
\w
Wybór lub
Znak | oznacza lub
Grupy
Okrywając kawałek wzoru nawiasami robimy z niego grupę, do której możemy się później odwoływać.
W powyższych przykładach używaliśmy metody .test(), która zwraca wartość boolean.
Przy pracy z grupami warto skorzystać z dodatkowych metod takich jak .match() lub .exec() czy replace(), które zwracają tablicę pasujących fragmentów:
Do kolejnych znalezionych członów (grup) możemy potem odwoływać się poprzez zapis $1, $2 itd.
Możemy to wykorzystać w metodzie replace(), ale też podczas pracy w edytorze tekstu.
Dopasowywane w zależności
Zapis ?= pozwala nam dopasowywać dany fragment tekstu, gdy tuż za nim występuje inny fragment tekstu:
W ES2018 mamy też bardzo podobny zapis ?<=, który pozwala nam sprawdzać czy dany ciąg poprzedza jakiś tekst:
Unicode w wyrażeniach regularnych
Domyślnie wyrażenia regularne - tak samo jak reszta tekstów w javascript operuje na pierwszych 1600 znakach z tablicy Unicode. Jeżeli chcielibyśmy działać na niestandardowych znakach (np. Chińskich literach czy ikonach Emoji), powinniśmy do naszego wzoru dodać flagę u:
Last updated