Wyrażenia Regularne (Regex) – Kompletny Przewodnik
1. Czym w ogóle jest Regex?
Regex to sposób, żeby powiedzieć komputerowi: „Sprawdź, czy ten tekst wygląda tak, jak ja chcę”.
Zamiast pisać 50 linijek kodu „czy ma myślnik, czy ma 5 cyfr itd.” – piszesz jeden magiczny wiersz.
W praktyce:
Zamiast pytać: „Czy to jest dokładnie tekst ‚jan@gmail.com’?”
Regex pozwala zapytać: „Czy to jest cokolwiek, co wygląda jak email?” (ma @, ma tekst przed i po @, kończy się kropką i domeną)
Kluczowa idea: Regex opisuje WZORZEC, nie konkretny tekst.
Przykład: Chcesz sprawdzić polski kod pocztowy 00-123 Zamiast pisać kod na 20 linijek, piszesz:
bool ok = Regex.IsMatch(kod, @"^\d{2}-\d{3}$");
| Co to jest? | Co oznacza po polsku? | Przykład |
|---|---|---|
| \d | jedna cyfra (0–9) | \d\d = 2 cyfry → „12”, „99” |
| {2} lub {5} | dokładnie tyle razy | \d{5} = dokładnie 5 cyfr |
| – | zwykły myślnik (piszesz go normalnie) | |
| ^ | „musi się zaczynać od…” | |
| $ | „musi się kończyć tutaj” |
2. Podstawowe elementy Regex.
Kotwice: ^ i $
Co to jest:
- ^ = „zacznij tutaj” (początek tekstu)
- $ = „zakończ tutaj” (koniec tekstu)
Dlaczego są KLUCZOWE przy walidacji formularzy?
Bez kotwic:
\d{3}
Znajdzie: 123 w tekście „abc123xyz” wartość zwróci True.
Z kotwicami:
^\d{3}$
Sprawdza: Czy CAŁY tekst to dokładnie 3 cyfry?
Zwróci prawdę gdy tekst jest „123” zwróci fałsz gdy tekst jest: „abc123xyz” ❌
Podsumowanie: Kotwice mówią „sprawdź, czy to pasuje OD POCZĄTKU DO KOŃCA”, nie tylko „czy gdzieś tam jest fragment”.
Przykład praktyczny:
// BEZ kotwic - akceptuje śmieci!
string regex1 = @"\d{5}";
Regex.IsMatch("abc12345xyz", regex1); // TRUE (znalazło 12345 w środku!)
// Z KOTWICAMI - waliduje poprawnie!
string regex2 = @"^\d{5}$";
Regex.IsMatch("abc12345xyz", regex2); // FALSE (bo to nie TYLKO cyfry)
Regex.IsMatch("12345", regex2); // TRUE
2.2 Klasy Znaków – Gotowe Szablony
\d – Cyfra (digit)
Co oznacza: Dowolna cyfra 0-9
Przykład:
\d\d\d
Znajdzie: 123, 999, 000
W C#:
string pattern = @"\d{3}"; // 3 cyfry
Regex.IsMatch("Mam 500 złotych", pattern); // TRUE
\w – Znak słowny (word character)
Co oznacza: Litera, cyfra lub podkreślenie [a-zA-Z0-9_]
Przykład:
\w+
Znajdzie: Hello, User123, nazwa_zmiennej
W C#:
string pattern = @"\w+";
Regex.IsMatch("Jan_Kowalski", pattern); // TRUE
Regex.IsMatch("Hello World!", pattern); // TRUE (znajdzie "Hello" i "World")
\s – Biała spacja (whitespace)
Co oznacza: Spacja, tab, nowa linia
Przykład:
\w+\s\w+
Znajdzie: Jan Kowalski (słowo + spacja + słowo)
W C#:
string pattern = @"\w+\s\w+";
Regex.IsMatch("Jan Kowalski", pattern); // TRUE
Regex.IsMatch("JanKowalski", pattern); // FALSE (brak spacji)
. – Kropka (dowolny znak)
Co oznacza: KAŻDY znak (oprócz nowej linii)
Przykład:
a.c
Znajdzie: abc, a1c, a@c, a c
UWAGA: To pułapka dla początkujących!
// ŹLE
string pattern1 = @"test.txt";
Regex.IsMatch("test1txt", pattern1); // TRUE (ups!)
// DOBRZE
string pattern2 = @"test\.txt";
Regex.IsMatch("test.txt", pattern2); // TRUE
Regex.IsMatch("test1txt", pattern2); // FALSE
2.3 Zestawy Własne: [...]
Co to jest: Nawiasy kwadratowe pozwalają stworzyć własną „listę dozwolonych znaków”.
[a-z] – Małe litery od a do z
Przykład:
[a-z]{3}
Znajdzie: abc, xyz, kot
W C#:
string pattern = @"^[a-z]{3}$";
Regex.IsMatch("abc", pattern); // TRUE
Regex.IsMatch("ABC", pattern); // FALSE (duże litery)
Regex.IsMatch("ab1", pattern); // FALSE (cyfra)
[0-9] – Cyfry od 0 do 9
Przykład:
[0-9]{2}
Znajdzie: 12, 99, 00
To samo co \d{2}!
Kombinacje i negacje
[a-zA-Z] # Dowolna litera (mała lub duża)
[0-9a-f] # Cyfry hex (0-9 oraz a-f)
[^0-9] # NEGACJA - wszystko OPRÓCZ cyfr
Przykład negacji:
string pattern = @"[^0-9]+"; // Wszystko oprócz cyfr
Regex.IsMatch("abcXYZ", pattern); // TRUE
Regex.IsMatch("123", pattern); // FALSE
2.4 Kwantyfikatory (Ile Razy?)
Co to jest: Określają, ile razy dany znak/grupa może się powtórzyć.
* – Zero lub więcej razy
Przykład:
ab*c
Znajdzie: ac (zero b), abc (jedno b), abbc (dwa b), abbbbbc
W C#:
string pattern = @"ab*c";
Regex.IsMatch("ac", pattern); // TRUE
Regex.IsMatch("abc", pattern); // TRUE
Regex.IsMatch("abbbbc", pattern); // TRUE
+ – Jeden lub więcej razy
Przykład:
ab+c
Znajdzie: abc, abbc, ale NIE ac (musi być przynajmniej jedno b)
W C#:
string pattern = @"ab+c";
Regex.IsMatch("ac", pattern); // FALSE (brak b)
Regex.IsMatch("abc", pattern); // TRUE
Regex.IsMatch("abbbc", pattern); // TRUE
? – Zero lub jeden raz (opcjonalny)
Przykład:
colou?r
Znajdzie: color (bez u) i colour (z u)
W C#:
string pattern = @"colou?r";
Regex.IsMatch("color", pattern); // TRUE
Regex.IsMatch("colour", pattern); // TRUE
Regex.IsMatch("colouur", pattern); // FALSE (dwa u)
{n,m} – Od n do m razy
Przykłady:
{3}– dokładnie 3 razy{3,}– 3 lub więcej razy{3,5}– od 3 do 5 razy
\d{2,4}
Znajdzie: 12, 123, 1234, ale NIE 1 (za mało) ani 12345 (za dużo, ale weźmie pierwsze 4)
W C#:
string pattern = @"^\d{2,4}$"; // Z kotwicami!
Regex.IsMatch("12", pattern); // TRUE
Regex.IsMatch("123", pattern); // TRUE
Regex.IsMatch("1234", pattern); // TRUE
Regex.IsMatch("1", pattern); // FALSE
Regex.IsMatch("12345", pattern); // FALSE
3. BARDZO WAŻNE: Verbatim String @"..."
Problem: Backslash \ w C#
W C# backslash \ to znak specjalny (escape character):
\n= nowa linia\t= tab\\= dosłowny backslash
Regex używa backslasha: \d, \w, \s, \.
Co się stanie BEZ małpy @?
// ŹLE - kompilator myśli, że \d to escape sequence!
string pattern = "\d{3}"; // ERROR lub nieprawidłowe działanie!
// Musiałbyś eskejpować podwójnie:
string pattern = "\\d{3}"; // Działa, ale brzydkie!
Rozwiązanie: Verbatim String @"..."
Małpa @ mówi: „Potraktuj ten string DOSŁOWNIE, nie interpretuj \„
// DOBRZE - czytamy dokładnie to, co widzimy
string pattern = @"\d{3}";
// Czyta się jak pisze:
// \d = regex dla cyfry
// {3} = dokładnie 3 razy
Porównanie:
// Bez @ - piekło eskejpowania
string sciezka1 = "C:\\Users\\Jan\\Documents";
string regex1 = "\\d{2}\\.\\d{2}\\.\\d{4}";
// Z @ - czytelne i proste
string sciezka2 = @"C:\Users\Jan\Documents";
string regex2 = @"\d{2}\.\d{2}\.\d{4}";
ZASADA: W regexach w C# ZAWSZE używaj @"..."
Walidacja Formularzy
4.1 Polski Kod Pocztowy (00-000)
Jak ja to buduję w głowie:
Krok 1: Co chcę zwalidować?
- Dwie cyfry
- Myślnik
- Trzy cyfry
- I NIC WIĘCEJ (całe pole!)
Krok 2: Rozkładam na kawałki:
Dwie cyfry: \d{2}
Myślnik: -
Trzy cyfry: \d{3}
Krok 3: Sklejam:
\d{2}-\d{3}
Krok 4: Dodaję kotwice (walidacja CAŁEGO pola!):
^\d{2}-\d{3}$
Krok 5: W C#:
public bool CzyPoprawnyKodPocztowy(string kod)
{
string pattern = @"^\d{2}-\d{3}$";
return Regex.IsMatch(kod, pattern);
}
// Testy:
Console.WriteLine(CzyPoprawnyKodPocztowy("00-950")); // TRUE
Console.WriteLine(CzyPoprawnyKodPocztowy("12-345")); // TRUE
Console.WriteLine(CzyPoprawnyKodPocztowy("1-234")); // FALSE (za mało cyfr)
Console.WriteLine(CzyPoprawnyKodPocztowy("00 950")); // FALSE (spacja zamiast myślnika)
Console.WriteLine(CzyPoprawnyKodPocztowy("abc-def")); // FALSE (litery)
4.2 Prosty Adres Email
Jak ja to buduję w głowie:
Krok 1: Co chcę znaleźć?
- Tekst przed @
- Małpa @
- Tekst po @ (domena)
- Kropka
- Rozszerzenie (pl, com, itp.)
Krok 2: Jakie znaki są dozwolone przed @?
- Litery, cyfry, kropki, myślniki, podkreślenia
[\w\.\-]+(jeden lub więcej)
Krok 3: Małpa:
@
Krok 4: Domena:
- Litery, cyfry, myślniki
[\w\-]+
Krok 5: Kropka (escape!):
\.
Krok 6: Rozszerzenie (2-6 liter):
[a-z]{2,6}
Krok 7: Sklejam z kotwicami:
^[\w\.\-]+@[\w\-]+\.[a-z]{2,6}$
W C#:
public bool CzyPoprawnyEmail(string email)
{
string pattern = @"^[\w\.\-]+@[\w\-]+\.[a-z]{2,6}$";
return Regex.IsMatch(email.ToLower(), pattern);
}
// Testy:
Console.WriteLine(CzyPoprawnyEmail("jan@gmail.com")); // TRUE
Console.WriteLine(CzyPoprawnyEmail("anna.nowak@wp.pl")); // TRUE
Console.WriteLine(CzyPoprawnyEmail("test_123@domain.co.uk")); // TRUE
Console.WriteLine(CzyPoprawnyEmail("brak-malpy.com")); // FALSE
Console.WriteLine(CzyPoprawnyEmail("@gmail.com")); // FALSE
Console.WriteLine(CzyPoprawnyEmail("jan@")); // FALSE
UWAGA: To uproszczona wersja! Pełna walidacja emaila to temat na osobny artykuł
4.3 Data RRRR-MM-DD
Jak ja to buduję w głowie:
Krok 1: Format:
- 4 cyfry (rok)
- Myślnik
- 2 cyfry (miesiąc)
- Myślnik
- 2 cyfry (dzień)
Krok 2: Rozkładam:
Rok: \d{4}
Myślnik: -
Miesiąc: \d{2}
Myślnik: -
Dzień: \d{2}
Krok 3: Sklejam z kotwicami:
^\d{4}-\d{2}-\d{2}$
UWAGA: To sprawdza tylko FORMAT, nie poprawność daty (np. 2025-13-99 przejdzie)!
W C#:
public bool CzyPoprawnFormatDaty(string data)
{
string pattern = @"^\d{4}-\d{2}-\d{2}$";
// Najpierw format
if (!Regex.IsMatch(data, pattern))
return false;
// Potem semantyczna walidacja
return DateTime.TryParseExact(data, "yyyy-MM-dd",
null, System.Globalization.DateTimeStyles.None, out _);
}
// Testy:
Console.WriteLine(CzyPoprawnFormatDaty("2025-01-15")); // TRUE
Console.WriteLine(CzyPoprawnFormatDaty("2025-12-31")); // TRUE
Console.WriteLine(CzyPoprawnFormatDaty("2025-13-99")); // FALSE (niepoprawna data)
Console.WriteLine(CzyPoprawnFormatDaty("25-01-15")); // FALSE (zły format)
Console.WriteLine(CzyPoprawnFormatDaty("2025/01/15")); // FALSE (slash zamiast myślnika)
Szybka Ściąga:
┌─ KOTWICE ─────────────────────────────────────────────────────
│ ^ Początek tekstu/linii
│ $ Koniec tekstu/linii
│ \b Granica słowa (np. \bkot\b znajdzie "kot", nie "kotek")
└───────────────────────────────────────────────────────────────
┌─ KLASY ZNAKÓW ────────────────────────────────────────────────
│ \d Cyfra [0-9]
│ \D Nie-cyfra [^0-9]
│ \w Znak słowny [a-zA-Z0-9_]
│ \W Nie-znak słowny
│ \s Biała spacja [ \t\n\r]
│ \S Nie-spacja
│ . Dowolny znak (oprócz \n)
└───────────────────────────────────────────────────────────────
┌─ KWANTYFIKATORY ──────────────────────────────────────────────
│ * 0 lub więcej
│ + 1 lub więcej
│ ? 0 lub 1 (opcjonalny)
│ {n} Dokładnie n
│ {n,} N lub więcej
│ {n,m} Od n do m
└───────────────────────────────────────────────────────────────
┌─ ZESTAWY [ ] ────────────────────────────────────────────────
│ [abc] Jeden z: a, b lub c
│ [a-z] Zakres: a do z
│ [^abc] NEGACJA: wszystko OPRÓCZ a, b, c
│ [a-zA-Z] Kombinacja zakresów
└───────────────────────────────────────────────────────────────
┌─ GRUPY I REFERENCJE ──────────────────────────────────────────
│ (abc) Grupa przechwytująca
│ (?:abc) Grupa nieprzechwytująca
│ a|b Alternatywa: a LUB b
│ (?=...) Lookahead (sprawdź, nie zużywaj)
└───────────────────────────────────────────────────────────────
┌─ ZNAKI SPECJALNE (wymagają escape \) ─────────────────────────
│ \. Dosłowna kropka
│ \* Dosłowna gwiazdka
│ \+ Dosłowny plus
│ \? Dosłowny znak zapytania
│ \[ \] Dosłowne nawiasy kwadratowe
│ \( \) Dosłowne nawiasy okrągłe
│ \\ Dosłowny backslash
└───────────────────────────────────────────────────────────────
┌─ C# REGEX OPTIONS ────────────────────────────────────────────
│ RegexOptions.IgnoreCase
│ RegexOptions.Multiline
│ RegexOptions.Singleline
│ RegexOptions.IgnorePatternWhitespace
└───────────────────────────────────────────────────────────────
┌─ C# METODY ───────────────────────────────────────────────────
│ Regex.IsMatch(text, pattern) → bool
│ Regex.Match(text, pattern) → Match object
│ Regex.Matches(text, pattern) → MatchCollection
│ Regex.Replace(text, pattern, replace) → string
└───────────────────────────────────────────────────────────────
┌─ NAJCZĘSTSZE WZORCE ──────────────────────────────────────────
│ Email: ^[\w\.\-]+@[\w\-]+\.[a-z]{2,6}$
│ Telefon: ^\d{3}-\d{3}-\d{3}$
│ Kod: ^\d{2}-\d{3}$
│ URL: ^https?://[\w\-\.]+\.[a-z]{2,}
│ IP: ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$
│ Data: ^\d{4}-\d{2}-\d{2}$
│ Hex: ^#[0-9a-fA-F]{6}$
└───────────────────────────────────────────────────────────────
Pliki do pobrania ćwiczeń poniżej:
