Wyrażenia regularne to specjalnie zakodowane ciągi tekstowe używane jako wzorce do dopasowywania zestawów ciągów znaków. Zaczęły pojawiać się w latach czterdziestych XX wieku jako sposób opisywania języków naturalnych, a do świata programowania weszły w latach siedemdziesiątych. Pierwsze miejsce, w którym je znalazłem, to edytor tekstu QED napisany przez Kena Thompsona.

Wyrażenie regularne to wzorzec, który określa zestaw ciągów znaków; mówi się, że pasuje do pewnych łańcuchów

Ken Thompson

Wyrażenia regularne stały się później ważną częścią zestawu narzędzi, który wyłonił się z systemu operacyjnego Unix – między innymi edytory ed, sed i vi (vim), grep, AWK.

Wyrażenia regularne pozwalają nam wykonywać złożone operacje wyszukiwania i zastępowania w tysiącach plików tekstowych w ciągu zaledwie kilku sekund.

Apple zapewnia obsługę wyrażeń regularnych na wszystkich swoich platformach – iOS, macOS, tvOS, a nawet watchOS – przy użyciu tej samej klasy, NSRegularExpression. Jest to niezwykle szybki i skuteczny sposób wyszukiwania i zastępowania złożonego tekstu dziesiątki tysięcy razy i jest dostępny dla programistów Swift.

W tym samouczku dowiesz się, jak tworzyć wyrażenia regularne przy użyciu NSRegularExpression oraz jak dopasowywać różne wyrażenia regularne przy użyciu najważniejszych elementów składni.

W wyrażeniach regularnych najczęściej wykorzystujemy następujące znaki:
  • ^ (daszek) rozpoczyna się od – dopasowuje wszystkie wyrażenia, które zaczynają się od danego wzoru np. ^tor dopasuje takie słowa jak tor, torowisko, torfowiec, torpeda, ale nie dopasuje już edytor, doktor, traktor itd.
  • $ (dolar)kończy się na – odwrotnie niż ^, dopasowuje wszystkie wyrażenia, które kończą się na daną frazę. Wracając do powyższego przykładu dla tor$ dopasowane zostanie tor, dyktator, edytor i doktor, ale nie torowisko, torfowiec czy torpeda.
 
  • | (rurka:P, ang. pipe)lub – w logice ładnie nazywa się to alternatywą. Dopasowuje wartości, które stoją po obu jej stronach np. dla wyrażenia ^sektor$|^wektor$ dopasowane zostanie słowo sektor lub wektor.
  • . (kropka)zastępuje jeden dowolny znak w wyrażeniu – wyrażenie ^..lie$ dopasuje takie słowa jak: kolie, folie, dalie (dwie kropki zastępują nam w tym przypadku dwie litery „ko”, „fo” lub „da”). Wyrażenie ^…owa$ dopasuje np.: kasowa, rasowa i rodowa ale okowa i sowa nie zostaną już dopasowane.
  • * (gwiazdka)zastępuje nieskończoną liczbę znaków po znaku, po którym następuje – najczęściej wykorzystuję ją w połączeniu z kropką. Dzięki temu połączeniu można znaleźć dowolny ciąg znaków np. ^d(.*)t$ dopasuje słowa: dramat, dyktat, dykt itp., czyli każdą frazę, która zaczyna się na „d” i kończy na „t” oraz ma przynajmniej 2 znaki.
  • + (plus)oznacza powtórzenie przynajmniej raz poprzedniego znaku, czyli dla wyrażenia ^maria+ zostaną dopasowane: maria, mariaa, mariaaa itd.
  • ? (znak zapytania) – oznacza brak wystąpienia lub wystąpienie jeden raz poprzedzającego znaku – dla wyrażenia maria? dopasowane zostaną jedynie: maria lub mari.
 
  • [ ] (nawiasy kwadratowe)oznaczają dopasowanie dowolnego pojedynczego znaku w ich ramach – dzięki wyrażeniu regularnemu [ck]on[vw]ersion dopasowane zostaną następujące frazy: conversion, konversion, conwersion oraz konwersion. Nawiasy kwadratowe w połączeniu z daszkiem w środku dopasują dowolny znak, który NIE znajduje się w sprawdzanej frazie np. dla wyrażenia [^abc] dopasuje każdy znak, poza trzema pierwszymi literami z alfabetu.
  • – (myślnik)oznacza zakres wyrażeń – najczęściej wykorzystuję go w połączeniu z nawiasem kwadratowym np. wyrażenie regularne wa[k-m|r-t]a dopasuje następujące frazy: wara, wasa, wata, waka, waja, wama. Możemy również wykorzystać cyfry tj. sektor[1-9] Wtedy zostaną dopasowane wyrażenia: sektor1, sektor2, sektor3 itd.
  • \ (backslash , czyli ukośnik tylny)przywraca standardowe znaczenie znaków wykorzystywanych w wyrażeniach regularnych – jak już zauważyliście, wyrażenia regularne wykorzystują znaki, które są nie rzadko wykorzystywane. Najlepszym przykładem jest kropka – w wyrażeniach regularnych oznacza dowolny znak, natomiast normalnie jest to oznaczenie końca zdania.
Na pewno zauważyliście, że stosując kombinację ^ oraz $ dostajemy coś w stylu dopasowania ścisłego np. dla wyrażenia ^sektor$ dopasuje nam tylko i wyłącznie słowo sektor.

Jak używamy wyrażeń regularnych?

				
					let regex = try! NSRegularExpression(pattern: "[a-z]at")
				
			

Powyżej zdefiniowane zostało wyrażenie regularne składające się z dowolnej małej litery od „a” do „z”, oraz napisu at. Czy pasującym będzie zarówno napis „kat”, jak i „mat”?

NSRegularExpression jest to inicjator, który rzuca wyjątkiem przy próbie podania nieprawidłowego wyrażenia regularnego. Podany przykład jest poprawny, więc nie zwróci błędu.

				
					let range = NSRange(location: 0, length: testString.utf16.count)
regex.firstMatch(in: testString, options: [], range: range) != nil
				
			

Pierwsza linia z nich tworzy NSRange obejmującą cały nasz ciąg. Ważne jest tu obliczanie długości wykorzystując reprezentację utf16. Druga linia szuka pierwszego dopasowania w naszym ciągu testowym. Jeśli będzie nilem, oznacza, że nie odnaleźliśmy szukanego wzorca.

Uwaga:

Utworzenie instancji NSRegularExpression wiąże się z dużymi kosztami m.in. w pamięci, więc jeśli zamierzasz wielokrotnie używać danego wyrażenia regularnego, lepiej będzie przechowywać zmienną z wyrażeniem regularnym typ NSRegularExpression do wielokrotnego użycia.

Do nauki wyrażeń regularnych polecamy stronę https://regex101.com.