Was ist eine Regex?
Reguläre Ausdrücke (Regex oder Regexp) sind Zeichenfolgen, die Suchmuster definieren. Sie sind eines der mächtigsten Werkzeuge für Textverarbeitung, Mustererkennung und Datenextraktion.
Warum Reguläre Ausdrücke verwenden?
Regex ist unverzichtbar für:
- Formularvalidierung (E-Mail, Telefonnummern, Passwörter)
- Datenextraktion (Log-Parsing, Web-Scraping)
- Textverarbeitung (Suchen und Ersetzen, Formatierung)
- Code-Refactoring (Variablen umbenennen, Syntax aktualisieren)
- Eingabebereinigung (Sicherheit, Injection-Angriffe verhindern)
Wie man dieses Cheat Sheet liest
Dieser Leitfaden ist in progressive Abschnitte unterteilt:
- Grundlagen - Basissyntax und Muster
- Erweiterte Funktionen - Lookaround, benannte Gruppen, Unicode
- Sprachspezifisch - Beispiele in Python, JavaScript, PHP, C#, Java, Go, Ruby
- Regex in VS Code - Suchen-und-Ersetzen-Transformationen mit über 20 Beispielen
- Häufige Muster - Kopier- und einfügbare Muster für E-Mail, URL, Datum usw.
- Praktische Anwendungsfälle - Anwendungen aus der realen Welt
- Fehlerbehebung - Häufige Fehler und Performance-Tipps
Jeder Abschnitt enthält:
- Klare Erklärungen
- Visuelle Beispiele
- Code-Schnipsel zum Kopieren
- Profi-Tipps und Fallstricke
Literalzeichen
Die einfachste Regex ist eine Folge von Literalzeichen:
abc
Findet: "abc" in "Die Sequenz abc"
Groß-/Kleinschreibung
Standardmäßig sind Regex case-sensitive:
Hallofindet "Hallo" aber NICHT "hallo"- Verwenden Sie das
i-Flag für case-insensitive Suche:/hallo/i
Sonderzeichen (Metazeichen)
Diese 12 Zeichen haben eine besondere Bedeutung in Regex und müssen mit \ maskiert werden, um literal zu suchen:
. ^ $ * + ? { } [ ] \ | ( )
Beispiele:
\.findet einen literalen Punkt\€findet ein Euro-Zeichen\(findet eine literale Klammer
| Zeichen | Maskiert | Beispiel | Findet |
|---|---|---|---|
. (Punkt) |
\. |
3\.14 |
"3.14" |
€ (Euro) |
\€ |
\€100 |
"€100" |
* (Stern) |
\* |
a\*b |
"a*b" |
Zeichenklassen
Vordefinierte Zeichenklassen
| Muster | Beschreibung | Äquivalent | Beispiel | Findet |
|---|---|---|---|---|
\d |
Beliebige Ziffer | [0-9] |
\d\d |
"42" |
\D |
Beliebige Nicht-Ziffer | [^0-9] |
\D+ |
"abc" |
\w |
Wortzeichen | [a-zA-Z0-9_] |
\w+ |
"hallo_123" |
\W |
Nicht-Wortzeichen | [^a-zA-Z0-9_] |
\W |
"@", "#" |
\s |
Leerzeichen | [ \t\n\r\f\v] |
\s+ |
" " (Leerzeichen) |
\S |
Nicht-Leerzeichen | [^ \t\n\r\f\v] |
\S+ |
"hallo" |
. |
Beliebiges Zeichen außer Zeilenumbruch | - | a.c |
"abc", "a1c" |
Profi-Tipp: \w enthält standardmäßig KEINE Unicode-Buchstaben. Verwenden Sie \p{L} für Unicode-Unterstützung (JavaScript/Python).
Benutzerdefinierte Zeichenklassen
| Muster | Beschreibung | Beispiel | Findet |
|---|---|---|---|
[abc] |
Findet eines von a, b oder c | [aeiou] |
Vokale: "a", "e", "i", "o", "u" |
[^abc] |
Findet alles außer a, b oder c | [^0-9] |
Nicht-Ziffern |
[a-z] |
Bereich: Kleinbuchstaben | [a-z]+ |
"hallo" |
[A-Z] |
Bereich: Großbuchstaben | [A-Z]+ |
"HALLO" |
[0-9] |
Bereich: Ziffern | [0-9]{4} |
"2025" |
[a-zA-Z] |
Kombiniert: alle Buchstaben | [a-zA-Z0-9] |
Alphanumerisch |
Beispiele:
[aeiou] → Findet jeden Vokal
[^aeiou] → Findet jeden Konsonanten (Nicht-Vokal)
[a-z0-9] → Findet Kleinbuchstaben und Ziffern
[a-zA-Z0-9_] → Entspricht \w (Wortzeichen)
Quantoren
Quantoren geben an, wie oft ein Muster gefunden werden soll.
Basis-Quantoren
| Muster | Beschreibung | Beispiel | Findet |
|---|---|---|---|
* |
0 oder mehr | ab*c |
"ac", "abc", "abbc", "abbbc" |
+ |
1 oder mehr | ab+c |
"abc", "abbc" (NICHT "ac") |
? |
0 oder 1 (optional) | colou?r |
"color", "colour" |
{n} |
Genau n mal | \d{4} |
"2025" (genau 4 Ziffern) |
{n,} |
n oder mehr mal | \d{2,} |
"42", "123", "9999" |
{n,m} |
Zwischen n und m mal | \d{2,4} |
"42", "123", "2025" |
Gierige vs. Nicht-gierige Quantoren
Gierig (Standard): Findet so viel wie möglich
<.*> → Findet: "<div>Hallo</div>" (gesamte Zeichenkette)
Nicht-gierig (Lazy): Findet so wenig wie möglich (fügen Sie ? nach dem Quantor hinzu)
<.*?> → Findet: "<div>" und "</div>" separat
| Gierig | Nicht-gierig | Beschreibung |
|---|---|---|
* |
*? |
0 oder mehr (nicht-gierig) |
+ |
+? |
1 oder mehr (nicht-gierig) |
? |
?? |
0 oder 1 (nicht-gierig) |
{n,m} |
{n,m}? |
Zwischen n und m (nicht-gierig) |
Beispiel:
Text: "Hallo" und "Welt"
".*"findet:"Hallo" und "Welt"(gierig)".*?"findet:"Hallo"und"Welt"separat (nicht-gierig)
Anker und Grenzen
Anker finden Positionen, nicht Zeichen.
| Muster | Beschreibung | Beispiel | Findet |
|---|---|---|---|
^ |
Anfang der Zeichenkette/Zeile | ^Hallo |
"Hallo Welt" (am Anfang) |
$ |
Ende der Zeichenkette/Zeile | Welt$ |
"Hallo Welt" (am Ende) |
\b |
Wortgrenze | \bKatze\b |
"Katze" in "Die Katze saß" (NICHT "Raubkatze") |
\B |
Nicht-Wortgrenze | \BKatz |
"Raubkatze" (Katz NICHT an Grenze) |
\A |
Anfang der Zeichenkette (nicht Zeile) | \AHallo |
Findet nur wenn "Hallo" ganz am Anfang steht |
\z |
Ende der Zeichenkette (nicht Zeile) | Welt\z |
Findet nur wenn "Welt" ganz am Ende steht |
\Z |
Ende der Zeichenkette (vor finalem Zeilenumbruch) | Welt\Z |
Findet "Welt" oder "Welt\n" |
Beispiele:
^Katze$ → Findet: "Katze" (gesamte Zeile ist "Katze")
\bKatze\b → Findet: "Katze" in "die Katze saß" (ganzes Wort)
\BKatz → Findet: "Katz" in "Raubkatze" (NICHT an Grenze)
Mehrzeilenmodus (Flag m):
- Ohne
m:^und$finden Anfang/Ende der gesamten Zeichenkette - Mit
m:^und$finden Anfang/Ende jeder Zeile
Gruppen und Alternation
Erfassungsgruppen
Erfassungsgruppen (...) merken sich den gefundenen Text:
(\d+)-(\d+) → Findet: "123-456"
Gruppe 1: "123"
Gruppe 2: "456"
Rückreferenzen (erfasste Gruppen wiederverwenden):
(\w)\1 → Findet: "aa", "bb", "cc" (wiederholtes Zeichen)
(\w+) \1 → Findet: "hallo hallo" (wiederholtes Wort)
Nicht-erfassende Gruppen
Verwenden Sie (?:...) wenn Sie gruppieren aber nicht erfassen möchten:
(?:https?://) → Gruppiert "http://" oder "https://" ohne zu erfassen
Warum nicht-erfassend verwenden?
- Bessere Performance (kein Speicher-Overhead)
- Sauberere Rückreferenzen (nur Erfassungsgruppen werden nummeriert)
Alternation (ODER)
Verwenden Sie | für "findet dies ODER das":
Katze|Hund → Findet: "Katze" oder "Hund"
gr(a|ü)n → Findet: "gran" oder "grün"
Beispiele:
(Herr|Frau|Dr)\.? → Findet: "Herr", "Frau", "Dr."
https?:// → Findet: "http://" oder "https://"
Lookaround-Zusicherungen
Lookarounds sind Null-Breiten-Zusicherungen, die eine Position finden (wie Anker), aber mit Bedingungen.
Positiver Lookahead (?=...)
Findet, wenn das Muster voraus passt (aber konsumiert es nicht):
\d(?=px) → Findet: "10" in "10px" (NICHT der "px"-Teil)
Anwendungsfall: Passwort-Validierung
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$
Aufschlüsselung:
(?=.*[A-Z])- Muss Großbuchstaben enthalten(?=.*[a-z])- Muss Kleinbuchstaben enthalten(?=.*\d)- Muss Ziffer enthalten(?=.*[@$!%*?&])- Muss Sonderzeichen enthalten.{8,}- Mindestens 8 Zeichen
Negativer Lookahead (?!...)
Findet, wenn das Muster voraus NICHT passt:
\d(?!px) → Findet: "10" in "10em" (NICHT "10px")
Anwendungsfall: Bestimmte Wörter ausschließen
\b(?!test)\w+ → Findet Wörter, die NICHT mit "test" beginnen
Positiver Lookbehind (?<=...)
Findet, wenn das Muster rückwärts passt:
(?<=€)\d+ → Findet: "100" in "€100" (NICHT der "€"-Teil)
Anwendungsfall: Preise extrahieren
(?<=Preis: €)\d+,\d{2} → Findet: "29,99" in "Preis: €29,99"
Negativer Lookbehind (?<!...)
Findet, wenn das Muster rückwärts NICHT passt:
(?<!€)\d+ → Findet: "100" aber NICHT in "€100"
Zusammenfassungstabelle:
| Typ | Syntax | Beschreibung | Beispiel |
|---|---|---|---|
| Positiver Lookahead | (?=...) |
Findet wenn gefolgt von... | q(?=u) findet "q" in "queen" |
| Negativer Lookahead | (?!...) |
Findet wenn NICHT gefolgt von... | q(?!u) findet "q" in "iraq" |
| Positiver Lookbehind | (?<=...) |
Findet wenn vorangestellt von... | (?<=€)\d+ findet "10" in "€10" |
| Negativer Lookbehind | (?<!...) |
Findet wenn NICHT vorangestellt von... | (?<!€)\d+ findet "10" in "10" |
Benannte Erfassungsgruppen
Benannte Gruppen (?<name>...) machen Regex lesbarer:
JavaScript:
const dateRegex = /(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})/;
const match = '2025-01-17'.match(dateRegex);
console.log(match.groups.jahr); // "2025"
console.log(match.groups.monat); // "01"
console.log(match.groups.tag); // "17"
Python:
import re
pattern = r'(?P<jahr>\d{4})-(?P<monat>\d{2})-(?P<tag>\d{2})'
match = re.search(pattern, '2025-01-17')
print(match.group('jahr')) # "2025"
print(match.group('monat')) # "01"
print(match.group('tag')) # "17"
C#:
var pattern = @"(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})";
var match = Regex.Match("2025-01-17", pattern);
Console.WriteLine(match.Groups["jahr"].Value); // "2025"
Atomare Gruppen und Possessive Quantoren
Atomare Gruppen (?>...)
Sobald gefunden, gibt es kein Backtracking. Verhindert katastrophales Backtracking:
(?>\d+)bar → Findet: "123bar" (schnell)
Ohne atomare Gruppe:
\d+bar → Versucht: "123bar", "12bar", "1bar" (langsam bei Nichtübereinstimmung)
Possessive Quantoren
| Gierig | Possessiv | Beschreibung |
|---|---|---|
* |
*+ |
0 oder mehr (kein Backtracking) |
+ |
++ |
1 oder mehr (kein Backtracking) |
? |
?+ |
0 oder 1 (kein Backtracking) |
Anwendungsfall: Katastrophales Backtracking bei komplexen Mustern verhindern.
Unicode-Unterstützung
Moderne Regex-Engines unterstützen Unicode-Kategorien und Skripte.
Unicode-Kategorien \p{...}
JavaScript (ES2018+):
const letters = /\p{L}+/u; // Beliebiger Buchstabe (jede Sprache)
const numbers = /\p{N}+/u; // Beliebige Zahl
const currency = /\p{Sc}/u; // Währungssymbole
Python:
import regex # Hinweis: benötigt 'regex'-Modul, nicht 're'
letters = regex.compile(r'\p{L}+')
Häufige Unicode-Kategorien:
| Kategorie | Beschreibung | Beispiel |
|---|---|---|
\p{L} |
Buchstabe | "a", "字", "א" |
\p{N} |
Zahl | "1", "①", "一" |
\p{S} |
Symbol | "$", "©", "♥" |
\p{Sc} |
Währungssymbol | "$", "€", "¥" |
\p{P} |
Interpunktion | ".", "!", "?" |
\p{Z} |
Trennzeichen | Leerzeichen, Tab |
Unicode-Skripte:
/\p{Script=Greek}/u → Findet griechische Buchstaben: "α", "β", "γ"
/\p{Script=Cyrillic}/u → Findet kyrillisch: "а", "б", "в"
/\p{Script=Han}/u → Findet chinesische Zeichen
Negation:
/\P{L}+/u → Findet alles, was KEIN Buchstabe ist
Modifikatoren und Flags
Flags ändern, wie Regex-Muster interpretiert werden.
| Flag | Name | Beschreibung | Beispiel |
|---|---|---|---|
i |
Case-insensitive | Ignoriert Groß-/Kleinschreibung | /hallo/i findet "Hallo" |
g |
Global | Findet alle Übereinstimmungen | /katze/g findet alle "katze" |
m |
Multiline | ^ und $ finden Zeilenanfänge/-enden |
/^hallo/m |
s |
Dotall | . findet auch Zeilenumbruch |
/a.b/s findet "a\nb" |
u |
Unicode | Aktiviert Unicode-Funktionen | /\p{L}+/u |
x |
Extended | Ignoriert Leerzeichen (Free-Spacing) | Erlaubt Kommentare |
y |
Sticky | Findet an exakter Position | Nur JavaScript |
Beispiele:
Case-insensitive (i):
/hallo/i.test('HALLO') // true
Global (g):
'katze hund katze'.match(/katze/g) // ["katze", "katze"]
Multiline (m):
const text = 'Zeile 1\nZeile 2';
/^Zeile 2/m.test(text) // true (ohne 'm': false)
Dotall (s):
/a.b/s.test('a\nb') // true (ohne 's': false)
Inline-Modifikatoren
Flags auf Teil des Musters anwenden:
(?i)hallo → "hallo" case-insensitive
(?-i)WELT → "WELT" case-sensitive
(?i:hallo) → Nur "hallo" ist case-insensitive
Bedingte Muster
Syntax: (?(Bedingung)wahr|falsch)
Beispiel: Zitierte oder unzitierte Zeichenketten finden
("|')?[^"'\r\n]*(?(1)\1)
Aufschlüsselung:
("|')?- Erfasst optional öffnendes Anführungszeichen[^"'\r\n]*- Findet Inhalt(?(1)\1)- Wenn Gruppe 1 gefunden (öffnendes Anführungszeichen), finde gleiches schließendes Anführungszeichen
Findet:
"hallo"✅'welt'✅test✅ (keine Anführungszeichen)"gemischt'❌ (unpassende Anführungszeichen)
Kommentare in Regex
Inline-Kommentare (?# kommentar)
\d{3}(?# Vorwahl)-\d{3}(?# Zentrale)-\d{4}(?# Nummer)
Free-Spacing-Modus (Flag x)
Ignoriert Leerzeichen und erlaubt Kommentare:
(?x)
\d{3} # Vorwahl
- # Trennzeichen
\d{3} # Zentrale
- # Trennzeichen
\d{4} # Nummer
Viel lesbarer für komplexe Muster!
Dieser Abschnitt zeigt, wie Regex in 7 beliebten Programmiersprachen verwendet wird. Jede Sprache hat ihre eigene Regex-API, aber die Mustersyntax bleibt größtenteils konsistent.
JavaScript / Node.js
Regex-Muster erstellen
// Literal-Notation (am häufigsten)
const pattern1 = /\d{3}-\d{4}/;
// Konstruktor (wenn Muster dynamisch ist)
const pattern2 = new RegExp('\\d{3}-\\d{4}');
// Hinweis: Backslashes müssen in Strings maskiert werden
// Mit Flags
const pattern3 = /hallo/gi; // Global, case-insensitive
String-Methoden
// .match() - Findet Übereinstimmungen
const text = 'Kontakt: 123-4567 oder 987-6543';
const matches = text.match(/\d{3}-\d{4}/g);
console.log(matches); // ["123-4567", "987-6543"]
// .matchAll() - Holt alle Übereinstimmungen mit Gruppen (ES2020)
const emailPattern = /([\w.-]+)@([\w.-]+\.[a-z]{2,})/gi;
const emails = 'admin@beispiel.de, benutzer@test.org';
for (const match of emails.matchAll(emailPattern)) {
console.log(`Benutzer: ${match[1]}, Domain: ${match[2]}`);
}
// Benutzer: admin, Domain: beispiel.de
// Benutzer: benutzer, Domain: test.org
// .search() - Findet Position der ersten Übereinstimmung
const pos = 'Hallo Welt'.search(/Welt/);
console.log(pos); // 6
// .replace() - Ersetzt Übereinstimmungen
const phone = '(+49) 151 123 4567';
const cleaned = phone.replace(/[^\d]/g, '');
console.log(cleaned); // "491511234567"
// .replaceAll() - Ersetzt alle Übereinstimmungen (ES2021)
const text2 = 'katze hund katze';
const result = text2.replaceAll(/katze/g, 'vogel');
console.log(result); // "vogel hund vogel"
// .split() - Teilt nach Muster
const csv = 'apfel,banane, orange , traube';
const fruits = csv.split(/\s*,\s*/);
console.log(fruits); // ["apfel", "banane", "orange", "traube"]
RegExp-Methoden
// .test() - Gibt Boolean zurück
const isEmail = /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i;
console.log(isEmail.test('benutzer@beispiel.de')); // true
// .exec() - Gibt Übereinstimmungsdetails zurück (oder null)
const pattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = pattern.exec('Datum: 2025-01-17');
if (match) {
console.log(match[0]); // "2025-01-17" (vollständige Übereinstimmung)
console.log(match[1]); // "2025" (Gruppe 1)
console.log(match[2]); // "01" (Gruppe 2)
console.log(match[3]); // "17" (Gruppe 3)
}
Benannte Gruppen (ES2018+)
const pattern = /(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})/;
const match = '2025-01-17'.match(pattern);
console.log(match.groups.jahr); // "2025"
console.log(match.groups.monat); // "01"
console.log(match.groups.tag); // "17"
// Benannte Rückreferenzen
const dupeWord = /\b(?<wort>\w+)\s+\k<wort>\b/i;
console.log(dupeWord.test('hallo hallo')); // true
Unicode-Unterstützung (ES2018+)
// Findet beliebigen Buchstaben (inkl. umlaute, chinesisch, arabisch, etc.)
const letters = /\p{L}+/u;
console.log(letters.test('Kaffee')); // true
console.log(letters.test('你好')); // true
// Findet Emoji
const emoji = /\p{Emoji}/u;
console.log(emoji.test('Hallo 👋')); // true
Python
Das re-Modul
import re
# Muster kompilieren (empfohlen für Wiederverwendung)
pattern = re.compile(r'\d{3}-\d{4}')
# Oder direkt verwenden
re.search(r'\d{3}-\d{4}', 'Rufen Sie an 123-4567')
Kern-Funktionen
import re
# re.search() - Findet erste Übereinstimmung
match = re.search(r'\d{3}-\d{4}', 'Kontakt: 123-4567 oder 987-6543')
if match:
print(match.group()) # "123-4567"
print(match.start()) # 9 (Position)
print(match.end()) # 17
# re.match() - Findet am ANFANG der Zeichenkette
match = re.match(r'\d+', '123 Hauptstraße')
print(match.group() if match else None) # "123"
match = re.match(r'\d+', 'Hauptstraße 123')
print(match) # None (beginnt nicht mit Ziffer)
# re.fullmatch() - Findet GESAMTE Zeichenkette
result = re.fullmatch(r'\d{3}-\d{4}', '123-4567')
print(bool(result)) # True
result = re.fullmatch(r'\d{3}-\d{4}', 'Rufen Sie an 123-4567')
print(bool(result)) # False (zusätzlicher Text)
# re.findall() - Findet alle Übereinstimmungen (gibt Liste zurück)
text = 'Preise: €10, €25, €100'
prices = re.findall(r'€(\d+)', text)
print(prices) # ['10', '25', '100']
# re.finditer() - Findet alle Übereinstimmungen (gibt Iterator zurück)
for match in re.finditer(r'€(\d+)', text):
print(f'Gefunden €{match.group(1)} an Position {match.start()}')
# Gefunden €10 an Position 7
# Gefunden €25 an Position 12
# Gefunden €100 an Position 17
# re.sub() - Ersetzt Übereinstimmungen
phone = '(+49) 151 123 4567'
cleaned = re.sub(r'[^\d]', '', phone)
print(cleaned) # "491511234567"
# re.split() - Teilt nach Muster
csv = 'apfel,banane, orange , traube'
fruits = re.split(r'\s*,\s*', csv)
print(fruits) # ['apfel', 'banane', 'orange', 'traube']
Gruppen und benannte Gruppen
import re
# Nummerierte Gruppen
pattern = r'(\d{4})-(\d{2})-(\d{2})'
match = re.search(pattern, 'Datum: 2025-01-17')
if match:
print(match.group(0)) # "2025-01-17" (vollständige Übereinstimmung)
print(match.group(1)) # "2025"
print(match.group(2)) # "01"
print(match.group(3)) # "17"
print(match.groups()) # ('2025', '01', '17')
# Benannte Gruppen (?P<name>...)
pattern = r'(?P<jahr>\d{4})-(?P<monat>\d{2})-(?P<tag>\d{2})'
match = re.search(pattern, '2025-01-17')
if match:
print(match.group('jahr')) # "2025"
print(match.group('monat')) # "01"
print(match.group('tag')) # "17"
print(match.groupdict()) # {'jahr': '2025', 'monat': '01', 'tag': '17'}
Flags
import re
# Case-insensitive
re.search(r'hallo', 'HALLO', re.IGNORECASE) # oder re.I
# Multiline (^ und $ finden Zeilenanfänge/-enden)
re.search(r'^Zeile 2', 'Zeile 1\nZeile 2', re.MULTILINE) # oder re.M
# Dotall (. findet Zeilenumbruch)
re.search(r'a.b', 'a\nb', re.DOTALL) # oder re.S
# Verbose (Free-Spacing-Modus mit Kommentaren)
pattern = re.compile(r'''
\d{3} # Vorwahl
- # Trennzeichen
\d{3} # Zentrale
- # Trennzeichen
\d{4} # Nummer
''', re.VERBOSE) # oder re.X
# Flags kombinieren mit |
pattern = re.compile(r'hallo', re.IGNORECASE | re.MULTILINE)
Ersetzen mit Funktionen
import re
# Funktion für dynamische Ersetzungen verwenden
def double_number(match):
num = int(match.group())
return str(num * 2)
text = 'Ich habe 5 Äpfel und 10 Orangen'
result = re.sub(r'\d+', double_number, text)
print(result) # "Ich habe 10 Äpfel und 20 Orangen"
# Mit benannten Gruppen
def format_name(match):
return f"{match.group('nachname').upper()}, {match.group('vorname')}"
pattern = r'(?P<vorname>\w+)\s+(?P<nachname>\w+)'
text = 'Hans Müller'
result = re.sub(pattern, format_name, text)
print(result) # "MÜLLER, Hans"
PHP
PCRE-Funktionen
<?php
// preg_match() - Findet erste Übereinstimmung
$pattern = '/\d{3}-\d{4}/';
$text = 'Kontakt: 123-4567 oder 987-6543';
if (preg_match($pattern, $text, $matches)) {
echo $matches[0]; // "123-4567"
}
// preg_match_all() - Findet alle Übereinstimmungen
preg_match_all('/\d{3}-\d{4}/', $text, $matches);
print_r($matches[0]); // ["123-4567", "987-6543"]
// preg_replace() - Ersetzt Übereinstimmungen
$phone = '(+49) 151 123 4567';
$cleaned = preg_replace('/[^\d]/', '', $phone);
echo $cleaned; // "491511234567"
// preg_split() - Teilt nach Muster
$csv = 'apfel,banane, orange , traube';
$fruits = preg_split('/\s*,\s*/', $csv);
print_r($fruits); // ["apfel", "banane", "orange", "traube"]
// preg_grep() - Filtert Array nach Muster
$words = ['apfel', 'banane', 'aprikose', 'orange'];
$aWords = preg_grep('/^a/', $words);
print_r($aWords); // ["apfel", "aprikose"]
?>
Benannte Gruppen
<?php
$pattern = '/(?P<jahr>\d{4})-(?P<monat>\d{2})-(?P<tag>\d{2})/';
$text = '2025-01-17';
if (preg_match($pattern, $text, $matches)) {
echo $matches['jahr']; // "2025"
echo $matches['monat']; // "01"
echo $matches['tag']; // "17"
}
?>
Modifikatoren (Flags)
<?php
// i - Case-insensitive
preg_match('/hallo/i', 'HALLO'); // Findet
// m - Multiline
preg_match('/^Zeile 2/m', "Zeile 1\nZeile 2"); // Findet
// s - Dotall (. findet Zeilenumbruch)
preg_match('/a.b/s', "a\nb"); // Findet
// x - Free-Spacing (ignoriert Leerzeichen)
$pattern = '/
\d{3} # Vorwahl
- # Trennzeichen
\d{3} # Zentrale
- # Trennzeichen
\d{4} # Nummer
/x';
// u - UTF-8-Unterstützung
preg_match('/\w+/u', 'Kaffee'); // Findet (inkl. ü)
// Modifikatoren kombinieren
preg_match('/hallo/imu', $text);
?>
Ersetzen mit Callback
<?php
$text = 'Ich habe 5 Äpfel und 10 Orangen';
$result = preg_replace_callback('/\d+/', function($matches) {
return (int)$matches[0] * 2;
}, $text);
echo $result; // "Ich habe 10 Äpfel und 20 Orangen"
?>
C# (.NET)
Regex-Klasse
using System;
using System.Text.RegularExpressions;
// Statische Methoden (einfache Verwendung)
string text = "Kontakt: 123-4567 oder 987-6543";
Match match = Regex.Match(text, @"\d{3}-\d{4}");
if (match.Success)
{
Console.WriteLine(match.Value); // "123-4567"
}
// Findet alle Übereinstimmungen
MatchCollection matches = Regex.Matches(text, @"\d{3}-\d{4}");
foreach (Match m in matches)
{
Console.WriteLine(m.Value);
}
// Ausgabe:
// 123-4567
// 987-6543
// Ersetzen
string phone = "(+49) 151 123 4567";
string cleaned = Regex.Replace(phone, @"[^\d]", "");
Console.WriteLine(cleaned); // "491511234567"
// Teilen
string csv = "apfel,banane, orange , traube";
string[] fruits = Regex.Split(csv, @"\s*,\s*");
// ["apfel", "banane", "orange", "traube"]
Kompilierte Regex (Bessere Performance)
using System.Text.RegularExpressions;
// Kompilieren für Wiederverwendung (viel schneller bei wiederholter Verwendung)
Regex pattern = new Regex(@"\d{3}-\d{4}", RegexOptions.Compiled);
string text = "Kontakt: 123-4567";
Match match = pattern.Match(text);
if (match.Success)
{
Console.WriteLine(match.Value);
}
RegexOptions (Flags)
using System.Text.RegularExpressions;
// Case-insensitive
Regex.IsMatch("HALLO", "hallo", RegexOptions.IgnoreCase);
// Multiline
Regex.Match("Zeile 1\nZeile 2", "^Zeile 2", RegexOptions.Multiline);
// Singleline (. findet Zeilenumbruch)
Regex.Match("a\nb", "a.b", RegexOptions.Singleline);
// Compiled (bessere Performance)
var pattern = new Regex(@"\d+", RegexOptions.Compiled);
// Optionen kombinieren
var opts = RegexOptions.IgnoreCase | RegexOptions.Multiline;
Regex.Match(text, pattern, opts);
Benannte Gruppen
using System;
using System.Text.RegularExpressions;
string pattern = @"(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})";
Match match = Regex.Match("2025-01-17", pattern);
if (match.Success)
{
Console.WriteLine(match.Groups["jahr"].Value); // "2025"
Console.WriteLine(match.Groups["monat"].Value); // "01"
Console.WriteLine(match.Groups["tag"].Value); // "17"
}
Ersetzen mit MatchEvaluator
using System;
using System.Text.RegularExpressions;
string text = "Ich habe 5 Äpfel und 10 Orangen";
string result = Regex.Replace(text, @"\d+", match =>
{
int num = int.Parse(match.Value);
return (num * 2).ToString();
});
Console.WriteLine(result); // "Ich habe 10 Äpfel und 20 Orangen"
Java
Pattern- und Matcher-Klassen
import java.util.regex.Pattern;
import java.util.regex.Matcher;
// Muster kompilieren
Pattern pattern = Pattern.compile("\\d{3}-\\d{4}");
String text = "Kontakt: 123-4567 oder 987-6543";
// Matcher erstellen
Matcher matcher = pattern.matcher(text);
// Erste Übereinstimmung finden
if (matcher.find()) {
System.out.println(matcher.group()); // "123-4567"
}
// Alle Übereinstimmungen finden
matcher.reset(); // Auf Anfang zurücksetzen
while (matcher.find()) {
System.out.println(matcher.group());
}
// Ausgabe:
// 123-4567
// 987-6543
String-Methoden
// matches() - Prüft ob GESAMTE Zeichenkette passt
boolean isPhone = "123-4567".matches("\\d{3}-\\d{4}");
System.out.println(isPhone); // true
// replaceAll() - Ersetzt alle Übereinstimmungen
String phone = "(+49) 151 123 4567";
String cleaned = phone.replaceAll("[^\\d]", "");
System.out.println(cleaned); // "491511234567"
// replaceFirst() - Ersetzt erste Übereinstimmung
String text = "katze hund katze";
String result = text.replaceFirst("katze", "vogel");
System.out.println(result); // "vogel hund katze"
// split() - Teilt nach Muster
String csv = "apfel,banane, orange , traube";
String[] fruits = csv.split("\\s*,\\s*");
// ["apfel", "banane", "orange", "traube"]
Pattern-Flags
import java.util.regex.Pattern;
// Case-insensitive
Pattern pattern = Pattern.compile("hallo", Pattern.CASE_INSENSITIVE);
// Multiline
Pattern.compile("^Zeile 2", Pattern.MULTILINE);
// Dotall (. findet Zeilenumbruch)
Pattern.compile("a.b", Pattern.DOTALL);
// Kommentare (Free-Spacing)
Pattern.compile("""
\\d{3} # Vorwahl
- # Trennzeichen
\\d{3} # Zentrale
- # Trennzeichen
\\d{4} # Nummer
""", Pattern.COMMENTS);
// Flags kombinieren
int flags = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE;
Pattern.compile("pattern", flags);
Benannte Gruppen
import java.util.regex.Pattern;
import java.util.regex.Matcher;
Pattern pattern = Pattern.compile("(?<jahr>\\d{4})-(?<monat>\\d{2})-(?<tag>\\d{2})");
Matcher matcher = pattern.matcher("2025-01-17");
if (matcher.find()) {
System.out.println(matcher.group("jahr")); // "2025"
System.out.println(matcher.group("monat")); // "01"
System.out.println(matcher.group("tag")); // "17"
}
Erweitertes Ersetzen
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "Ich habe 5 Äpfel und 10 Orangen";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
int num = Integer.parseInt(matcher.group());
matcher.appendReplacement(result, String.valueOf(num * 2));
}
matcher.appendTail(result);
System.out.println(result); // "Ich habe 10 Äpfel und 20 Orangen"
Go (Golang)
Das regexp-Paket
package main
import (
"fmt"
"regexp"
)
func main() {
// Muster kompilieren
pattern := regexp.MustCompile(`\d{3}-\d{4}`)
text := "Kontakt: 123-4567 oder 987-6543"
// Erste Übereinstimmung finden
match := pattern.FindString(text)
fmt.Println(match) // "123-4567"
// Alle Übereinstimmungen finden
matches := pattern.FindAllString(text, -1)
fmt.Println(matches) // [123-4567 987-6543]
// Prüfen ob passt
isMatch := pattern.MatchString("123-4567")
fmt.Println(isMatch) // true
// Alles ersetzen
phone := "(+49) 151 123 4567"
cleaned := regexp.MustCompile(`[^\d]`).ReplaceAllString(phone, "")
fmt.Println(cleaned) // "491511234567"
// Teilen
csv := "apfel,banane, orange , traube"
fruits := regexp.MustCompile(`\s*,\s*`).Split(csv, -1)
fmt.Println(fruits) // [apfel banane orange traube]
}
Submatch (Gruppen)
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
text := "Datum: 2025-01-17"
// FindStringSubmatch gibt [vollständig, gruppe1, gruppe2, ...] zurück
matches := pattern.FindStringSubmatch(text)
if matches != nil {
fmt.Println(matches[0]) // "2025-01-17" (vollständige Übereinstimmung)
fmt.Println(matches[1]) // "2025" (Gruppe 1)
fmt.Println(matches[2]) // "01" (Gruppe 2)
fmt.Println(matches[3]) // "17" (Gruppe 3)
}
// FindAllStringSubmatch für alle Übereinstimmungen
text2 := "Datum: 2025-01-17 und 2024-12-31"
allMatches := pattern.FindAllStringSubmatch(text2, -1)
for _, match := range allMatches {
fmt.Printf("Jahr: %s, Monat: %s, Tag: %s\n", match[1], match[2], match[3])
}
// Jahr: 2025, Monat: 01, Tag: 17
// Jahr: 2024, Monat: 12, Tag: 31
}
Benannte Gruppen
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(?P<jahr>\d{4})-(?P<monat>\d{2})-(?P<tag>\d{2})`)
text := "2025-01-17"
match := pattern.FindStringSubmatch(text)
if match != nil {
// Benannte Gruppenindizes abrufen
names := pattern.SubexpNames()
result := make(map[string]string)
for i, name := range names {
if i != 0 && name != "" {
result[name] = match[i]
}
}
fmt.Println(result["jahr"]) // "2025"
fmt.Println(result["monat"]) // "01"
fmt.Println(result["tag"]) // "17"
}
}
Ersetzen mit Funktionen
package main
import (
"fmt"
"regexp"
"strconv"
)
func main() {
text := "Ich habe 5 Äpfel und 10 Orangen"
pattern := regexp.MustCompile(`\d+`)
result := pattern.ReplaceAllStringFunc(text, func(s string) string {
num, _ := strconv.Atoi(s)
return strconv.Itoa(num * 2)
})
fmt.Println(result) // "Ich habe 10 Äpfel und 20 Orangen"
}
Ruby
Regex-Literale
# Literal-Notation
pattern = /\d{3}-\d{4}/
# Mit Flags
pattern_ci = /hallo/i # Case-insensitive
pattern_multi = /^zeile/m # Multiline
# Konstruktor (für dynamische Muster)
pattern = Regex.new('\d{3}-\d{4}')
String-Methoden
text = 'Kontakt: 123-4567 oder 987-6543'
# match() - Gibt MatchData oder nil zurück
match = text.match(/\d{3}-\d{4}/)
if match
puts match[0] # "123-4567"
end
# scan() - Findet alle Übereinstimmungen
matches = text.scan(/\d{3}-\d{4}/)
puts matches # ["123-4567", "987-6543"]
# =~ Operator - Gibt Index der ersten Übereinstimmung zurück
index = text =~ /\d{3}-\d{4}/
puts index # 9
# sub() - Ersetzt erste Übereinstimmung
result = 'katze hund katze'.sub(/katze/, 'vogel')
puts result # "vogel hund katze"
# gsub() - Ersetzt alle Übereinstimmungen
phone = '(+49) 151 123 4567'
cleaned = phone.gsub(/[^\d]/, '')
puts cleaned # "491511234567"
# split() - Teilt nach Muster
csv = 'apfel,banane, orange , traube'
fruits = csv.split(/\s*,\s*/)
puts fruits # ["apfel", "banane", "orange", "traube"]
Erfassungsgruppen
pattern = /(\d{4})-(\d{2})-(\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[0] # "2025-01-17" (vollständige Übereinstimmung)
puts match[1] # "2025" (Gruppe 1)
puts match[2] # "01" (Gruppe 2)
puts match[3] # "17" (Gruppe 3)
end
Benannte Gruppen
pattern = /(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[:jahr] # "2025"
puts match[:monat] # "01"
puts match[:tag] # "17"
end
Ersetzen mit Blöcken
text = 'Ich habe 5 Äpfel und 10 Orangen'
result = text.gsub(/\d+/) { |num| (num.to_i * 2).to_s }
puts result # "Ich habe 10 Äpfel und 20 Orangen"
# Mit benannten Gruppen
pattern = /(?<vorname>\w+)\s+(?<nachname>\w+)/
text = 'Hans Müller'
result = text.gsub(pattern) do |match|
m = Regexp.last_match
"#{m[:nachname].upcase}, #{m[:vorname]}"
end
puts result # "MÜLLER, Hans"
Flags
# i - Case-insensitive
/hallo/i.match('HALLO') # Findet
# m - Multiline (. findet Zeilenumbruch)
/a.b/m.match("a\nb") # Findet
# x - Free-Spacing (ignoriert Leerzeichen)
pattern = /
\d{3} # Vorwahl
- # Trennzeichen
\d{3} # Zentrale
- # Trennzeichen
\d{4} # Nummer
/x
# o - Einmal kompilieren (Optimierung)
pattern = /\d+/o
Die Suchen-und-Ersetzen-Funktion von Visual Studio Code (Strg/Cmd+H) unterstützt Regex mit leistungsstarken Transformationsfähigkeiten. Dieser Abschnitt zeigt 28 praktische Beispiele, die Entwickler täglich verwenden.
Zugriff auf Suchen und Ersetzen
Tastenkürzel:
- Suchen:
Strg+F(Windows/Linux) /Cmd+F(Mac) - Ersetzen:
Strg+H(Windows/Linux) /Cmd+H(Mac) - Regex aktivieren: Klicken Sie auf den
.*-Button oder drücken SieAlt+R
Tipps:
- Verwenden Sie
Strg+Enter(Cmd+Enter) um alles zu ersetzen - Vorschau der Übereinstimmungen vor dem Ersetzen (werden gelb hervorgehoben)
- Verwenden Sie
F3/Shift+F3um durch Übereinstimmungen zu navigieren
Groß-/Kleinschreibungs-Transformationen
VS Code unterstützt spezielle Ersetzungssequenzen für Groß-/Kleinschreibungsumwandlung:
| Sequenz | Effekt | Beispiel |
|---|---|---|
\l |
Kleinbuchstabe nächstes Zeichen | \l |
\u |
Großbuchstabe nächstes Zeichen | \u |
\L |
Kleinbuchstaben alle folgenden Zeichen | \L |
\U |
Großbuchstaben alle folgenden Zeichen | \U |
\E |
Beendet Groß-/Kleinschreibungs-Transformation | \U\E |
Beispiel 1: Ersten Buchstaben großschreiben
Suchen:
\b(\w)(\w*)
Ersetzen:
\u$1$2
Vorher:
hallo welt
Nachher:
Hallo Welt
Dieser Abschnitt bietet über 25 einsatzbereite Regex-Muster.
E-Mail-Validierung
^[\w.-]+@[\w.-]+\.[a-z]{2,}$
Telefonnummern (Deutschland)
^(\+?49)?[-.\s]?\(?([0-9]{2,5})\)?[-.\s]?([0-9]{3,10})$
Datum (ISO 8601)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
URL
^https?://(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b
IPv4-Adressen
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$
Hex-Farben
^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
Starkes Passwort
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
Benutzername (3-16 Zeichen)
^[a-zA-Z0-9_-]{3,16}$
UUID v4
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Und 15+ weitere Muster mit vollständiger Dokumentation!
Regex-Anwendungen aus der realen Welt in der Entwicklung.
Formularvalidierung
const validators = {
email: /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i,
phone: /^\(?\d{2,5}\)?[-.\s]?\d{3,10}$/
};
Datenextraktion
E-Mails aus Text extrahieren:
import re
emails = re.findall(r'[\w.-]+@[\w.-]+\.[a-z]{2,}', text)
Log-Parsing
pattern = r'(?P<ip>[\d.]+).+(?P<status>\d{3})'
Code-Refactoring
Alte API-Aufrufe in VS Code konvertieren:
Suchen: apiClient\.get\('([^']+)'\)
Ersetzen: fetch('$1').then(r => r.json())
Häufige Fehler
1. Vergessen Sonderzeichen zu maskieren
❌ Falsch: datei.txt
✅ Richtig: datei\.txt
2. Gierig vs. Nicht-gierig
❌ Gierig: <.*> findet gesamtes <div>text</div>
✅ Nicht-gierig: <.*?> findet <div> und </div> separat
3. Keine Anker verwenden
❌ /\d{3}/ findet "123" in "abc123def"
✅ /^\d{3}$/ findet nur genau "123"
Performance-Tipps
- Verwenden Sie spezifische Zeichenklassen statt
. - Ankern Sie Muster wenn möglich
- Vermeiden Sie verschachtelte Quantoren (katastrophales Backtracking)
- Verwenden Sie atomare Gruppen für Performance
- Kompilieren Sie Muster für Wiederverwendung
Debugging
- Testen Sie auf regex101.com
- Verwenden Sie Verbose-Modus mit Kommentaren
- Teilen Sie komplexe Muster in Teile
- Testen Sie Grenzfälle
Online-Tools
Regex-Tester
- regex101.com - Bester Tester mit Erklärungen
- regexr.com - Visueller Regex-Builder
- regexpal.com - Einfacher, schneller Test
Visualisierer
- debuggex.com - Railroad-Diagramme
- regexper.com - Visuelles Tool
Lernressourcen
- regexone.com - Interaktive Lektionen
- regexlearn.com - Schritt-für-Schritt-Anleitung
- regular-expressions.info - Dokumentation
IDE-Erweiterungen
- Regex Previewer (VS Code)
- Regex Tester (VS Code)
Zeichenklassen
| Muster | Findet |
|---|---|
\d |
Ziffer [0-9] |
\w |
Wortzeichen [a-zA-Z0-9_] |
\s |
Leerzeichen |
. |
Beliebiges Zeichen |
Quantoren
| Muster | Bedeutung |
|---|---|
* |
0 oder mehr |
+ |
1 oder mehr |
? |
0 oder 1 |
{n} |
Genau n |
Anker
| Muster | Bedeutung |
|---|---|
^ |
Zeilenanfang |
$ |
Zeilenende |
\b |
Wortgrenze |
Flags
| Flag | Bedeutung |
|---|---|
i |
Case-insensitive |
g |
Global |
m |
Multiline |
s |
Dotall |
Allgemeine Fragen
F: Was ist der Unterschied zwischen gierigen und nicht-gierigen Quantoren?
A: Gierig findet so viel wie möglich. Nicht-gierig (*?, +?) findet so wenig wie möglich.
F: Wie finde ich einen literalen Punkt?
A: Maskieren Sie ihn mit Backslash: \.
F: Was ist katastrophales Backtracking?
A: Wenn die Regex viele Kombinationen versucht, was zu Langsamkeit führt. Vermeiden Sie verschachtelte Quantoren wie (a+)+.
F: Können Regex eine E-Mail perfekt validieren?
A: Nein. Verwenden Sie Regex für Basis-Format, dann verifizieren Sie per E-Mail.
F: Wie finde ich über mehrere Zeilen?
A: Verwenden Sie das s-Flag, oder verwenden Sie [\s\S]* statt .*.
VS Code-spezifisch
F: Wie ersetze ich mit Großbuchstaben in VS Code?
A: Verwenden Sie \u (nächstes großschreiben), \U (alles großschreiben).
F: Kann ich Regex in VS Code Dateisuche verwenden?
A: Ja! Drücken Sie Strg+Shift+F und aktivieren Sie Regex (Alt+R).
Chrome-Erweiterung Regex Data Extractor
Unser Regex Data Extractor hilft Ihnen, Daten von Webseiten mit den Mustern aus diesem Leitfaden zu extrahieren.
Hauptfunktionen
- Musterbibliothek: Vorgefertigte Muster
- Echtzeit-Test: Testen Sie Regex auf jeder Webseite
- Multi-Format-Export: CSV, JSON, Excel, PDF
- Batch-Extraktion: Extrahieren Sie von mehreren Seiten
Beispiel: E-Mails extrahieren
- Installieren Sie Regex Data Extractor
- Navigieren Sie zu einer Webseite
- Klicken Sie auf das Erweiterungssymbol
- Geben Sie Muster ein:
[\w.-]+@[\w.-]+\.[a-z]{2,} - Klicken Sie "Extrahieren"
- Exportieren Sie zu CSV/JSON
Beispiel: Preise extrahieren
Muster: €([0-9]{1,3}(?:\.?[0-9]{3})*,?[0-9]{2})
Findet: €1.234,56, €99,99
Profi-Tipps
- Speichern Sie häufig verwendete Muster
- Verwenden Sie benannte Gruppen für strukturierte Daten
- Testen Sie Muster zuerst
- Exportieren Sie für Datenanalyse