Wyrażenia regularne w JavaScript

More advanced JavaScript

Poziom średnio-zaawansowany

Dziś omówimy jeden z nieco trudniejszych tematów, mianowicie wyrażenia regularne. Oczywiście naprawdę trudne są te najbardziej rozbudowane i zaawansowane wyrażenia. Wszystko jednak rekompensuje się w możliwościach, jakie daje to narzędzie!

Wyrażenia regularne w JavaScript

Wyrażenia regularne (Regular Expressions) są sposobem zapisania wzorca, z którym mogą być porównywane ciągi znaków, celem sprawdzania czy dany ciąg pasuje do podanego wzorca, a także celem wyszukiwania podciągów i ewentualnej zmiany bądź weryfikacji, itp.

Przykładowo można podać listę znaków które mogą pojawić się na danej pozycji (wewnątrz nawiasów kwadratowych):

// po literze "a" ma pojawić się cyfra od 0 do 7:
a[01234567]

Jeśli więc po znaku „a” pojawi się któraś z podanych cyfr, wzorzec zostanie dopasowany.

Istnieją także wersje skrócone tzn. z podaniem zakresów: a[0-7], czy też [a-z], [A-Z], itp.

Możliwe jest zanegowanie listy, poprzez znak ^:

[^0-9a-zA-Z]

Sekwencje specjalne

Dostępne są specjalne sekwencje, zastępujące predefiniowane zestawy znaków:

– \d – dowolna cyfra: [0-9]
– \D – dowolny znak nie będący cyfrą: [^0-9]
– \w – dowolna cyfra, litera (mała lub duża) lub znak podkreślenia: [0-9a-zA-Z_]
– \W – dowolny znak nie będący cyfrą, literą ani znakiem podkreślenia: [^0-9a-zA-Z_]
– \s – dowolny biały znak: [ \t\r\n\v\f]
– \S – dowolny znak nie-biały: [^ \t\r\n\v\f]

Znaki specjalne:

– \t – znak tabulacji poziomej (0x09)
– \v – znak tabulacji pionowej (0x0B)
– \r – „powrót karetki” (0x0D)
– \n – znak nowej linii (0x0A)
– \f – wysunięcie strony (0x0C)

Powtórzenia wzorca

W trakcie pisania wyrażeń regularnych często zdarza się, że pewien fragment wzorca powinien się powtórzyć. Służą do tego specjalne kwalifikatory, które umieszczone w wyrażeniu regularnym określają ile razy może (lub musi) powtórzyć się element znajdujący się tuż przed nim.

Oto lista:

{n} – dokładnie n wystąpień poprzedzającego wyrażenia
{n,} – n lub więcej wystąpień poprzedzającego wyrażenia
{n,m} – od n do m wystąpień poprzedzającego wyrażenia
? – element poprzedzający jest opcjonalny (może wystąpić 0 lub 1 raz)
+ – element poprzedzający może wystąpić jeden lub więcej razy
* – element poprzedzający może wystąpić zero lub więcej razy

Przykład:

/t{1,2}/ pasuje do wyrazów tekście mających 't', 'tt'

Znaki dosłowne (literalne) – czyli zwykłe znaki, tak umieszczone mają dokładnie takie znaczenie, np.:

/a/ pasuje do 'a' w tekście "access"

Flagi

Istnieją trzy flagi, których można użyć w wyrażeniach regularnych JavaScript:

g – szukaj globalnie – wyrażenie regularne szuka w tekście ciągów pasujących do wzoru tworząc tablicę wszystkich wystąpień tych ciągów

i – ignoruj wielkość liter

m – wieloliniowe wejście, że znak początku tekstu (^) i końca tekstu ($) są także w kolejnych liniach znakami początku i końca linii; słowem przetwarzanie ma dotyczyć ciągu zawierającego wiele wierszy

Przykład:

/fooBar/i;

Przejdźmy do użycia wyrażeń regularnych w JavaScript

Wyrażenie regularne w JS może zostać utworzone na dwa sposoby:

1. Poprzez wykorzystanie literału,

2. Poprzez formalne wywołanie konstruktora RegExp.

W pierwszym przypadku należy umieścić w kodzie wyrażenie zawarte pomiędzy prawymi ukośnikami, które może być dodatkowo zakończone znacznikami (flagami), w postaci:
/wyrażenie/[flagi]

W przypadku drugim wyrażenie tworzone jest za pomocą następującej konstrukcji:

new RegExp("wyrazenie"[, "flagi"])

// a
/(ab)+c/gi

// b
new RegExp("(ab)+c", "gi")

Wyrażenia oznaczone w przykładzie jako a i b są równoznaczne.

Jak widać nie umieszczamy wyrażenia regularnego cudzysłowie lub w apostrofach, ale pomiędzy znakami / oraz /.


Metody obiektów typu RegExp i String do obsługi wyrażeń regularnych

RegExp.compile(wyrazenie[, flagi]) – metoda compile dokonuje wewnętrznej kompilacji wyrażenia, co pozwala na późniejsze szybsze jego przetwarzanie. Wyrażenie może zawierać flagi i, g, m, których znaczenie jest takie samo jak w przypadku konstrukcji nowego wyrażenia.

RegExp.exec(wzorzec) – wykonuje przeszukanie ciągu str, wykorzystując wzorzec zawarty w wyrażeniu regularnym i zwraca tablicę wynikową.

Przykład – użycie metody RegExp.exec():

// przykład 1
var result = /s(amp)le/i.exec("My Sample Text");
// wynik: "Sample","amp"

// przykład 2
var str = "Ola ma kota, a Ala ma psa.";
var regexp = /Ala/;
var wynik = regexp.exec(str);
for (index in wynik){
    document.write("wynik[" + index + "] = " 
       + wynik[index] + "<br />");
}

RegExp.test(wzorzec) – zwraca true, jeśli ciąg znaków zawiera wzorzec pasujący do wyrażenia, false jeśli nie zawiera.

Przykład – użycie metody RegExp.test():

// przykład 1
/ala/i.test("Ola ma kota, a Ala ma psa."); //wynik: true

// przykład 2
var pasuje = /sample/.test("My Sample text");
// wynik: false (ze względu na wielkość liter / brak flagi "i")

String.match(wzorzec) – metoda ta porównuje ciąg znaków z wyrażeniem regularnym, celem dopasowania.

Przykład – uzycie String.match():

var str = "Programming with RoR".match(/r?or?/gi);
// wynik dopasowania: ["ro","RoR"]

String.search(wzorzec) – porównuje wyrażenie regularne z ciągiem znaków i zwraca indeks początku pasującego ciągu lub -1 jeżeli nic nie dopasuje.

Przykład – użycie String.search():

var idx = "Looking for JavaScript tips...".search(/for/);
// wynik: 8

String.replace(wzorzec, string) – zamienia miejsca, w których nastąpiło dopasowanie do wzorca.

Przykład – użycie String.replace():

// przykład 1
var str = "Ala ma kota".replace(/Ala/i, 'Ola');
// wynik: Ola ma kota

// przykład 2
var re = /(\w+)\s(\w+)/;
var str = "Jan Kowalski";
var newstr = str.replace(re, "$2, $1");
document.write(newstr); // wynik: "Kowalski, Jan"

Skrypt używa symboli „$1” i „$2” do oznaczenia wyników odpowiadających im nawiasów we wzorze wyrażenia regularnego.

String.split(wzorzec) – metoda rozbija (dzieli) ciąg znaków do postaci tablicy w miejscach gdzie dopasuje wzór.

Przykład – użycie String.split():

var str = "I am happy!".split(/\s/g);
// wynik: ["I","am","happy"]

I w tym momencie mamy kompletną skrzynkę narzędziową, aby pracować z wyrażeniami regularnymi w JavaScript.

Na koniec kilka przykładów praktycznych.

Przykład – parsowanie adresu URL:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

var url = "http://www.serwer.com:80/stuff?q#fragment";
var result = parse_url.exec(url);
var names = ['url', 'protokol', 'ukosniki', 'serwer', 'port',
    'path', 'zapytanie', 'zakotwiczenie'];

var blanks = '              ';
var i;
for (i = 0; i < names.length; i += 1) {
    document.writeln(names[i] + ':' + blanks.substring(
        names[i].length), result[i]);
}

Przykład – usuwanie łamania linii z ciągu znaków (np.: nagłówka strony):

var reg = new RegExp("(<br| /)>", "i");
sub_header_content = header_content.replace(reg, "");

Kolejne dwa przykłady, to funkcje, które już na stałe wchodzą w skład bibliotek dołączanych przeze mnie do niektórych projektów, nad którymi pracowałem.

Obie służą do walidacji wartości podawanych w formularzach. Pierwsza sprawdza, czy wpisano tylko liczby. Druga to walidacja adresu e-mail.

Przykład – walidator pozwalający wpisać tyko liczby:

/**
 * Allow: 0-9 digits only
 */
function onlyDigitsUtil(input) {
    var out    = "";
    var dt     = 0;
    var result = "";

    var regExp = /[0-9]+/;
    result = regExp.exec(input);
    
    if (result !== null) {
        dt = result.length;
        
        for (var i = 0; i < dt; i++) {
            out += result[i];
        }
    }

    return out;
}

Przykład – walidacja adresu e-mail w JavaScript:

/**
 * Email address - quick check
 */
function emailValidatorQuickTest(fieldVal) {
    // pattern
    var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;

    if (!filter.test(fieldVal)) {
        return false;
    }

    return true;
}

Mały test dla chętnych i dociekliwych: jak zmienić wyrażenie regularne (var filter), aby było znacznie krótsze? Podpowiedź: flaga /i.

Podsumowanie

Same wyrażenia regularne to temat na całą książkę. Mam nadzieję, że ten krótki artykuł wystarczy do sprawnego posługiwania się wyrażeniami regularnymi w JavaScript.

Dla czujących niedosyt, polecam podstronę Regular Expressions w MDN, szczególnie godna uwagi jest tabela z listą i opisem znaków specjalnych, używanych przy wyrażeniach regularnych.

/Dziękuję za uwagę./

Programista WWW i aplikacji mobilnych z wieloletnim doświadczeniem, początkujący bloger. Pasjonat programowania, nowych technologii, e-commerce, a także sportu i motoryzacji.

Twitter LinkedIn Google+ Skype Xing 

Podaj dalej: Share on Facebook1Tweet about this on TwitterShare on Google+1Share on LinkedIn2Share on Tumblr0Digg thisEmail this to someonePin on Pinterest1
Możesz skomentować leave a response, lub podać trackback z własnej strony.