RegExp Cheatsheet - Wyrażenia Regularne

Kompleksowa ściągawka dotycząca wyrażeń regularnych (RegExp). Zawiera podstawy, metaznaki, kwantyfikatory, grupy, flagi oraz przykłady użycia w JavaScript i PHP, wraz z poradami optymalizacyjnymi i zasadami czystego kodu.

1. Podstawy RegExp

Definicja i Zastosowanie

  • Definicja: Wyrażenia regularne to sekwencje znaków tworzące wzorzec wyszukiwania. Pozwalają na precyzyjne dopasowywanie, wyszukiwanie i manipulowanie ciągami znaków.
  • Zastosowanie:
    • Walidacja danych (e-maile, numery telefonów, daty).
    • Parsowanie logów, plików konfiguracyjnych.
    • Wyszukiwanie i zamiana tekstu.
    • Wydobywanie informacji ze stringów.
  • Składnia:
    • Większość języków używa separatorów (np. /pattern/flags w JS, /pattern/flags lub "pattern" w PHP z funkcjami preg_).
    • Znaki specjalne (metaznaki) muszą być escapowane (\).

Flagi (Modyfikatory)

Flaga Nazwa Opis
i Case-insensitive Ignoruje wielkość liter (A pasuje do a).
g (JS) Global Znajduje wszystkie dopasowania, nie tylko pierwsze.
m Multiline Traktuje string jako wiele linii; ^ i $ pasują na początku/końcu każdej linii.
u (PHP) Unicode Włącza obsługę znaków Unicode (np. \p{L} dla liter).
x (PHP) Extended Pozwala na białe znaki i komentarze w wyrażeniu dla lepszej czytelności.
s (PHP) Dotall Kropka (.) pasuje również do znaku nowej linii (\n).

2. Metaznaki i Klasy Znaków

Metaznaki (Specjalne Znaki)

Znak Opis Przykład Pasuje do
. Dowolny znak (oprócz \n, chyba że z flagą s) a.b axb, a#b
\d Cyfra (digit) [0-9] \d{3} 123
\D Nie-cyfra \D a, _
\w Znak słowa (word character) [a-zA-Z0-9_] \w+ tekst_1
\W Nie-znak słowa \W !,
\s Biały znak (whitespace) [ \t\n\r\f\v] hello\sWorld hello World
\S Nie-biały znak \S+ NoSpace
\b Granica słowa (word boundary) \bword\b a word, ale nie another_word
\B Nie-granica słowa \Bword anotherword
^ Początek linii/stringa ^Start Start of text
$ Koniec linii/stringa End$ Text ends with End

Escapowanie (Ucieczka) Znaków Specjalnych

  • Aby dopasować metaznak jako znak literalny, należy go poprzedzić ukośnikiem wstecznym (\).
  • Znaki do escapowania: . \ + * ? [ ] ^ $ ( ) { } = ! < > | : -
  • Przykład: Aby dopasować www.example.com, użyj www\.example\.com.

Klasy Znaków [...]

  • Definiują zestaw znaków, z których ma zostać dopasowany jeden znak.
  • Przykład: [abc] pasuje do a, b lub c.
  • Zakresy: [a-z] (małe litery), [A-Z] (duże litery), [0-9] (cyfry).
  • Negacja: [^abc] pasuje do dowolnego znaku OPRÓCZ a, b lub c.
  • Przykłady:
    • [aeiou]: Dowolna samogłoska.
    • [0-9a-fA-F]: Cyfry heksadecymalne.

Alternatywy | (OR)

  • Pozwala dopasować jeden z kilku wzorców.
  • Przykład: (cat|dog) pasuje do cat lub dog.

3. Kwantyfikatory

Liczba Wystąpień

Kwantyfikator Opis Przykład Pasuje do
* Zero lub więcej wystąpień a*b b, ab, aaab
+ Jedno lub więcej wystąpień a+b ab, aaab (ale nie b)
? Zero lub jedno wystąpienie (opcjonalny) colou?r color, colour
{n} Dokładnie n wystąpień \d{4} 1234
{n,} Co najmniej n wystąpień \d{2,} 12, 123, 12345
{n,m} Od n do m wystąpień \d{3,5} 123, 1234, 12345

Zachłanność (Greedy) vs. Nie-zachłanność (Lazy)

  • Domyślnie kwantyfikatory są **zachłanne (greedy)**: dopasowują jak najdłuższy możliwy ciąg.
  • Aby uczynić je **nie-zachłannymi (lazy)**, dodaj ? po kwantyfikatorze (np. *?, +?, ??, {n,}?).
  • Przykład zachłanny:
    /<.*>/
    Dla stringu <b>Hello</b> dopasuje <b>Hello</b>
  • Przykład nie-zachłanny:
    /<.*?>/
    Dla stringu <b>Hello</b> dopasuje <b> i </b> oddzielnie.

4. Grupowanie i Odniesienia Wsteczne

Grupy Zbierające (Capturing Groups) (...)

  • Pozwalają grupować wzorce i traktować je jako pojedynczą jednostkę.
  • Treść dopasowana przez grupę może być później użyta (odniesienia wsteczne).
  • Przykład: (ab)+ pasuje do ab, abab, ababab.

Grupy Niezbierające (Non-Capturing Groups) (?:...)

  • Grupują wzorzec, ale nie "zbierają" dopasowanej treści. Używane dla struktury wzorca bez dodatkowego obciążenia pamięci.
  • Przykład: (?:red|blue) car.

Odniesienia Wsteczne (Backreferences) \1, \2, ...

  • Pozwalają odwołać się do tekstu dopasowanego przez wcześniej zdefiniowaną grupę zbierającą.
  • Numer \n odnosi się do n-tej grupy.
  • Przykład: (\w+)\s\1 pasuje do podwojonych słów, np. hello hello.

Lookahead i Lookbehind (Assertions)

  • Mechanizmy sprawdzające obecność (lub brak) wzorca po/przed bieżącą pozycją, ale bez włączania go do dopasowania.
  • Positive Lookahead: (?=pattern) - pasuje, jeśli pattern występuje po bieżącej pozycji.
    • Przykład: \w+(?=\s*zł) - dopasuje słowo, po którym następuje " zł" (np. "100" w "100 zł").
  • Negative Lookahead: (?!pattern) - pasuje, jeśli pattern NIE występuje po bieżącej pozycji.
    • Przykład: \d{3}(?!\d) - dopasuje trzy cyfry, po których nie ma kolejnej cyfry.
  • Positive Lookbehind: (?<=pattern) - pasuje, jeśli pattern poprzedza bieżącą pozycję (PHP, JS ES2018+).
    • Przykład: (?<=\$)\d+ - dopasuje cyfry poprzedzone znakiem dolara (np. "100" w "$100").
  • Negative Lookbehind: (?<!pattern) - pasuje, jeśli pattern NIE poprzedza bieżącej pozycji (PHP, JS ES2018+).
    • Przykład: (?<!pre)fix - dopasuje "fix", jeśli nie jest poprzedzone przez "pre".

5. Wyrażenia Regularne w JavaScript

Obiekt RegExp i Metody Stringa

  • Tworzenie:
    // Literal (preferowany dla stałych wzorców)
    const regexLiteral = /abc/i;
    
    // Konstruktor (dla dynamicznych wzorców)
    const pattern = 'abc';
    const flags = 'i';
    const regexConstructor = new RegExp(pattern, flags);
    
  • Metody Stringa:
    Metoda Opis
    string.match(regex) Zwraca tablicę wszystkich dopasowań lub null. Jeśli z flagą g, wszystkie dopasowania; bez g, tylko pierwsze z grupami zbierającymi.
    string.search(regex) Zwraca indeks pierwszego dopasowania lub -1.
    string.replace(regex, replacement) Zastępuje dopasowany tekst.
    string.split(regex) Dzieli string na tablicę podciągów.
    string.matchAll(regex) (ES2020+) Zwraca iterator dla wszystkich dopasowań, z pełnymi szczegółami grup. Wymaga flagi g.
  • Metody Obiektu RegExp:
    Metoda Opis
    regex.test(string) Zwraca true jeśli jest dopasowanie, false w przeciwnym razie.
    regex.exec(string) Zwraca tablicę z pierwszym dopasowaniem i grupami zbierającymi, lub null. Przydatne w pętli z flagą g.
  • Przykład (JS): Walidacja e-maila
    (() => {
        const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
        const validateEmail = (email) => {
            return emailRegex.test(email);
        };
    
        console.log(validateEmail('test@example.com')); // true
        console.log(validateEmail('invalid-email'));    // false
    })();
    
  • Przykład (JS): Parsowanie URL
    (() => {
        const url = "https://www.example.com/path/to/page?id=123&name=test#section";
        const urlRegex = /^(https?):\/\/([^\/]+)([^?#]*)\??([^#]*)(?:#(.*))?$/;
        const matches = url.match(urlRegex);
    
        if (matches) {
            const [, protocol, host, path, query, hash] = matches;
            console.log(`Protocol: ${protocol}`);   // https
            console.log(`Host: ${host}`);           // www.example.com
            console.log(`Path: ${path}`);           // /path/to/page
            console.log(`Query: ${query}`);         // id=123&name=test
            console.log(`Hash: ${hash}`);           // section
        }
    })();
    

6. Wyrażenia Regularne w PHP

Funkcje preg_*

  • PHP używa PCRE (Perl Compatible Regular Expressions), co oferuje szeroki zakres funkcjonalności.
  • Ważne: Wzorce RegExp w PHP muszą być ujęte w **separatory** (np. /, #, ~).
  • Funkcje:
    Funkcja Opis
    preg_match($pattern, $subject, $matches) Szuka pierwszego dopasowania. Zwraca 1 jeśli znaleziono, 0 w przeciwnym razie. $matches zawiera dopasowania.
    preg_match_all($pattern, $subject, $matches) Szuka wszystkich dopasowań. Zwraca liczbę znalezionych dopasowań.
    preg_replace($pattern, $replacement, $subject) Zastępuje wszystkie dopasowania.
    preg_split($pattern, $subject) Dzieli string na tablicę.
    preg_grep($pattern, $array) Zwraca elementy tablicy, które pasują do wzorca.
  • Przykład (PHP): Wyszukiwanie tagów HTML
    <?php
    $html = "<p>To jest <b>pogrubiony</b> tekst.</p>";
    $pattern = '/<([a-z]+)>(.*?)<\/\1>/'; // \1 odnosi się do pierwszej grupy zbierającej (nazwy tagu)
    preg_match_all($pattern, $html, $matches);
    
    echo "<pre>";
    print_r($matches);
    echo "</pre>";
    /* Wynik:
    Array
    (
        [0] => Array
            (
                [0] => <p>To jest <b>pogrubiony</b> tekst.</p>
                [1] => <b>pogrubiony</b>
            )
        [1] => Array
            (
                [0] => p
                [1] => b
            )
        [2] => Array
            (
                [0] => To jest <b>pogrubiony</b> tekst.
                [1] => pogrubiony
            )
    )
    */
    ?>
    
  • Przykład (PHP): Walidacja numeru telefonu (polski format)
    <?php
    // Akceptuje: 123-456-789, 123 456 789, +48 123 456 789, +48123456789
    $phoneNumber = "+48 123 456 789";
    $pattern = '/^(?:\+48[\s-]?)?(\d{3}[\s-]?\d{3}[\s-]?\d{3})$/';
    
    if (preg_match($pattern, $phoneNumber, $matches)) {
        echo "Numer poprawny: " . $matches[1]; // 123 456 789
    } else {
        echo "Numer niepoprawny.";
    }
    ?>
    
---

SŁOWNICZEK POJĘĆ