Artykuł

maj 30 2009
0

Walidacja danych przy pomocy wyrażeń regularnych

W czasie tworzenia stron internetowych czy różnorodnych aplikacji desktopowych, niejednokrotnie stajemy przed problemem: Jak poprawnie zwalidować przychodzące dane?. W przypadku stron www, można to zrobić właściwie na dwa sposoby:

  • walidując dane po stronie klienta
  • walidując dane po stronie serwera

I tak naprawdę, zawsze powinniśmy korzystać z obu sposobów. Zatem jak walidować dane? Można to robić na wiele sposobów, np. sprawdzać rodzaj przychodzących danych, sprawdzać długość danych, rozbijać łańcuchy według określonych separatorów itp. Jednak są to rozwiązania niezwykle czasochłonne i często nieskuteczne. Ale jest nadzieja. Większość języków pozwala na korzystanie z wyrażeń regularnych. O tym czym one są i jak się je stosuje napiszę w dzisiejszym artykule

Idea wyrażeń regularnych

Wyrażenia regularne pozwalają w szybki sposób walidować nasze dane, jednak aby dobrze z nich korzystać potrzeba trochę cierpliwości i nauki. Walidacja odbywa się na podstawie wzorca danych, który definiujemy w wyrażeniu regularnym. Każdy wzorzec składa się ze znaków alfanumerycznych oraz metaznaków. Spójrzmy na przykładowe wyrażenie:

^[a-zA-z0-9]{1,10}$

Powyższe wyrażenie pasuje do dowolnego łańcucha znakowego, który posiada od jednego do dziesięciu znaków z grupy a-z, A-Z, 0-9. Zapis powyższego wzorca zapewne na razie nie jest do końca zrozumiały, ale poszczególne jego elementy zostaną przedstawione w kolejnych punktach. Wzorzec przedstawiony na listingu daje nam obraz jak prosto i łatwo można zbudować wyrażenie regularne opisujące dowolny łańcuch znaków. W następnym akapicie przedstawimy grupę podstawowych metaznaków pozwalających na tworzenie wyrażeń regularnych.

Metaznaki w wyrażeniach regularnych

Metaznaki są używane do tworzenia wyrażeń regularnych, pozwalają na tworzenie zaawansowanych konstrukcji służących do walidacji danych. Przyjrzyjmy się poniższej liście metaznaków:

  • \ - ogólny znak ucieczki, stosujemy go wtedy kiedy wewnątrz wzorca chcemy użyć jednego z metaznaków lub separatora
  • + - pasuje do znaku poprzedzającego lub podwzorca jeden lub więcej razy. Przykładowo:
    ko+t
    Dopasuje zarówno słowo kot, koot, kooot itd.
  • ? - pasuje do znaku poprzedzającego lub podwzorca
  • * - pasuje do znaku poprzedzającego zero lub więcej razy. Przykładowo:
    ko*t
    Pozwoli dopasować słowa kt, kot, koot, kooot itd.
  • | - pozwala na tworzenie wzorców zawierających spójnik lub. Przykładowo:
    ^a|b$
    Dopasuje literkę a LUB literkę b
  • {m} - pasuje do znaku poprzedzającego lub podwzorca m razy. Przykładowo:
    a{5}
    Dopasuje wzorzec, który będzie składał się z pięciu liter a
  • {m,n} - konstrukcja podobna do powyższej, różnica polega na tym że ilość powtórzeń zawiera się w przedziale od m do n
  • ^ - wskazuje początek wyrażenia; znak potęgi użyty wewnątrz klasy znaków (patrz niżej), pozwala na negację określonej klasy znaków
  • $ - wskazuje koniec wyrażenia
  • [...] - pozwala na tworzenie klas znaków, jest to jedna z ważniejszych konstrukcji wyrażeń regularnych. Spójrzmy na przykłady:
    [a-z]
    [A-Z]
    [0-9]
    [a-zA-Z0-9]
    [abcdef]
    Przykład w pierwszej lini pozwala na dopasowanie znaku będącego dowolną małą literą z przedziału a-z, analogicznie w linii drugiej dopasowujemy duże litery z przedziału A-Z, w linii trzeciej cyfry z zakresu 0-9, w linii czwartej dowolny z wyżej wymienionych znaków, a w linii piątej jedną z liter: a, b, c, d, e lub f. Grupowanie klas znaków szczególnego znaczenia nabiera kiedy zastosujemy metaznak powtórzenia. Przykłady:
    [a-z]{1,9}
    [a-z0-9]{1,9}
    Pierwszych z przedstawionych powyżej przykładów dopasuje każde słowo składające się z małych liter z przedziału a-z i będące długości o 1 do 9 znaków, drugi przykład jest podobny, z tym że w we wskazanym ciągu znaków mogą wystąpić również cyfry z przedziału 0-9
  • (...) - tworzy podwzorzec, w szybki i prosty sposób umożliwia podzielenie określonego wzorca na grupy wyników

Sekwencje ucieczki

Sekwencje ucieczki używane są kiedy chcemy użyć z góry zdefiniowanego znaku będącego w określonej grupie. Sekwencje ucieczki tworzone są w oparciu o znak backslasha. Przykładowe sekwencje ucieczki zaprezentowano poniżej:

  • \\ - sekwencja pozwalająca na stosowanie backslasha wewnątrz wzorca
  • \n - znak nowego wiersza
  • \r - znak powrotu karetki
  • \t - znak tabulacji
  • \d - dowolna cyfra z zakresu 0-9
  • \D - dowolny znak który nie jest cyfrą z zakresu 0-9
  • \s - dowolny biały znak
  • \S - dowolny znak, który nie jest białym znakiem
  • \w - dowolny znak, który nie jest składnikiem jakiegoś słowa, przykładowo może to być pojedyncza litera, cyfra lub znak podkreślenia
  • \W - dowolny znak, zaprzeczający powyższy zapis (\w)

Przykłady wyrażeń regularnych

W przypadku bardziej złożonych zagadnień, cieżko jest znaleźć idealne wyrażenie, które wyłapie wszystkie możliwe warianty, np. problem taki stanowi walidacja adresu e-mail. Poniższe wzorce stanowią przykłady dla kilku popularnych sytuacji.

Walidacja daty

^((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$

Powyższy przykład sprawdzi datę przedstawioną w postaci:

YYYY-MM-DD

gdzie Y to cyfra roku, M - cyfra miesiąca, a D - cyfra dnia. Powyższy przykład ogranicza się do dopasowywania dat z XX i XXI wieku.

Walidacja czasu

^(20|21|22|23|[01]d|d)(([:][0-5]d){1,2})$

Powyższy przykład sprawdzi godzinę w postaci:

HH:MM

gdzie H to cyfra godziny, a M cyfra minuty. Przykład powyższy sprawdza wszystkie godziny w 24 godzinnym trybie godzinowym.

Walidacja adresu e-mail

^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)$

Jest to jeden z wielu przykładów, który w dość szybki sposób testuje większość kombinacji. Jeśli chcemy mieć pełną kontrolę adresów e-mail nawet kosztem wydajności, skorzystajmy ze standardu RFC 2822:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Powyższy zapis jest bardzo zaawansowanym wzorcem i część z jego elementów nie została opisana w tym artykule.

Tworzenie wyrażeń regularnych w JavaScript

Do tworzenia wyrażeń regularnych w JavaScript wykorzystamy klasę RegExp. Poniższy kod tworzy nowy obiekt RegExp:

var oRegExp = new RegExp('^[a-z]{5}$');

Stworzyliśmy nowy obiekt, zawierąjacy wzorzec pozwalający na szukanie słów składających się z 5 liter i zawierających znaki z przedziału a-z. Teraz możemy sprawdzić czy przykładowe łańcuchy tekstowe będą pasować do naszego wzorca. Aby tego dokonać wykorzystamy metodę test z klasy RegExp, która zwraca prawdę (true), w wypadku gdy określony łańcuch pasuje do wzorca, lub fałsz (false) w przeciwnym wypadku. Przyjrzyjmy się przykładowi poniżej:

var sTest1 = 'lalal';
var sTest2 = '143avx';
var sTest3 = 'a';
var oRegExp = new RegExp('^[a-z]{5}$');
var bResult1 = oRegExp.test(sTest1);
var bResult2 = oRegExp.test(sTest2);
var bResult3 = oRegExp.test(sTest3);

Myślę że przykład jest prosty, dokonajmy jednak analizy. Pierwszy łańcuch oczywiście się klasyfikuje ponieważ spełnia kryterium długości i używa dozwolonych znaków. Drugi wzorzec już nie przejdzie. Znalazły się tutaj cyfry, ponadto wskazany wzorzec jest za długi. Trzeci wzorzec używa dozwolonego znaku, ale jest on za krótki.

Aby uprościć sobie testowanie możemy zbudować prostą funkcję:

function CheckIsValid(sPattern, sSourceString){
	var oRegExp = new RegExp(sPattern);
	return oRegExp.test(sSourceString);
}

Powyższa funkcja przyjmuje dwa argumenty:

  • sPattern - wzorzec wyrażenia regularnego
  • sSourceString - łancuch wejściowy

Jako rezultat otrzymamy wartość typu boolean: true przypadku gdy łańcuch wejściowy pasuje do wzorca, false w przeciwnym razie.

Metoda test, jest jedna z wielu użytych w klasie RegExp. Zachęcam do zapoznania się z pozostałymi metodami. Ich opis można znaleźć na przykład na stronie w3schools.

Źródła

Artykuł powstał w oparciu o przykłady ze strony Regular-Expressions.info oraz na podstawie książki PHP 5 - Tajniki programowania (Andi Gutmans, Stig Saether Bakken, Derick Rethans) oraz na bazie własnych doświadczeń.

Data ostatniej modyfikacji: 05.06.2011, 17:23.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus