Reguläre Ausdrücke (kurz: Regex, RegExp) sind eine kompakte Sprache, mit der sich Text-Muster beschreiben lassen — von einfachen Wortsuchen bis zu komplexen Substitutionen. In der GLAM- und DH-Praxis tauchen sie überall auf, wo grosse Mengen Text inspiziert oder umgeformt werden: Fehlersuche in OCR-Output, Massen-Korrektur in TEI-Dateien, Datums-Normalisierung, Validierung von Erschliessungs-Feldern.
Regex ist nicht eine Sprache, sondern eine Familie mit kleinen Dialekt-Unterschieden. Die wichtigsten Varianten in der Praxis:
| Variante | Wo |
|---|---|
| POSIX Basic (BRE) | grep ohne Optionen, sed |
| POSIX Extended (ERE) | grep -E, egrep, awk |
| PCRE (Perl-Compatible) | grep -P, ripgrep (rg), ack, viele Editoren |
| JavaScript | Visual Studio Code, Browser |
| ICU | LibreOffice |
| Word-Wildcards | MS Word — kein echtes Regex |
In der Praxis am häufigsten: PCRE-ähnliche Syntax, mit kleinen Stolpersteinen beim Wechsel zwischen Tools.
Grundbausteine
| Token | Bedeutung |
|---|---|
. | beliebiges Zeichen (ausser Newline) |
\d \w \s | Ziffer · Wort-Zeichen · Whitespace |
\D \W \S | jeweils das Negativ |
[abc] | eine der Optionen |
[a-z] | Bereich |
[^abc] | nicht eines davon |
^ $ | Zeilen-/String-Anfang/Ende |
\b | Wortgrenze |
* + ? | 0+ · 1+ · 0 oder 1 (greedy) |
*? +? ?? | dasselbe lazy (so wenig wie möglich) |
{n} {n,m} | exakt n · n bis m |
(...) | Capture-Gruppe |
(?:...) | Non-Capture-Gruppe |
(?<name>...) | Named-Capture (PCRE/JS) |
\1 \2 $1 $2 | Backreferenz auf Capture-Gruppe |
| `a | b` |
(?=...) (?!...) | Lookahead positiv / negativ |
(?<=...) (?<!...) | Lookbehind positiv / negativ |
Beispiele aus dem GLAM-Alltag
# Schweizer Datum DD.MM.YYYY
\b\d{1,2}\.\d{1,2}\.\d{4}\b
# ISO-Datum YYYY-MM-DD
\b\d{4}-\d{2}-\d{2}\b
# E-Mail (vereinfacht)
\b[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}\b
# DOI
\b10\.\d{4,9}/[-._;()/:A-Za-z0-9]+\b
# GND-ID-Pattern (ohne Bindestrich-Variante)
\b\d{6,9}\b
# TEI-Tag (start oder end) für Personen
</?persName[^>]*>
# Mehrere Leerzeichen
\s{2,}
# „seit/bis-Datierung" mit zwei Jahreszahlen
(\d{4})[\s\-–]+(\d{4})
# Whitespace am Zeilenanfang
^\s+
# Eine Zeile, die nicht mit Doppelpunkt endet
^(?!.*:\s*$).*\S$
In grep / ack / ripgrep
grep ist auf jedem Unix-System; ripgrep (rg) ist heute der pragmatische Standard für Code- und Textsuche, ack der ältere Verwandte. Alle drei können Regex; ripgrep und ack sind defaultmässig PCRE-nah, grep nutzt BRE und braucht -E oder -P für mehr.
# Einfache Suche
grep -E '\b\d{4}-\d{2}-\d{2}\b' datei.txt
rg '\b\d{4}-\d{2}-\d{2}\b' .
# Case-insensitive, mit Zeilennummern, Kontext
grep -niE '...' datei.txt
rg -in '...' .
# Nur Dateinamen mit Treffer
grep -lE '...' *.xml
rg -l '...' .
# Zeilen, die NICHT matchen
grep -vE '^#' config.ini
# Nur die Treffer (statt der ganzen Zeile)
grep -oE '\b10\.\d{4,9}/\S+\b' *.bib
# Über Verzeichnisse, mit Glob-Filter
grep -rE 'persName' --include='*.xml' .
rg 'persName' -g '*.xml'
# Multiline (PCRE-Modus, mit -P bzw. -U)
grep -Pzo '(?s)<persName>.*?</persName>' datei.xml
rg -U --multiline 'persName>[\s\S]*?</persName' .
# Suchen + Ersetzen (sed; macOS und GNU unterscheiden sich beim -i-Backup)
sed -E 's/\b(\d{4})-(\d{2})-(\d{2})\b/\3.\2.\1/g' datei.txt
ripgrep ist bei grossen Datenmengen typisch um eine Grössenordnung schneller als grep, respektiert .gitignore automatisch und hat saubere Defaults — Empfehlung für die Code-/Daten-Recherche im Alltag.
In Visual Studio Code
VS Code hat Regex direkt im Find/Replace-Dialog (Cmd-F für Find, Cmd-Alt-F für Find/Replace, oder im Search-Panel mit Cmd-Shift-F für Workspace-weite Suche). Den Regex-Modus einschalten mit dem .*-Knopf rechts neben dem Eingabefeld (oder Alt-R).
# Find:
<persName ref="(\w+)">
# Replace (in $-Notation):
<persName ref="https://d-nb.info/gnd/$1">
# Find: Datums-Format ändern
\b(\d{1,2})\.(\d{1,2})\.(\d{4})\b
# Replace: ISO-Datum mit Padding
$3-$2-$1
# Find: leere TEI-Tags entfernen
<(\w+)\s*>\s*</\1>
# Replace: (leer)
Wichtig in VS Code:
- Capture-Backrefs in Replace mit
$1,$2, …, nicht\1(einzige Ausnahme:\nfür Newline ist erlaubt). - Multiline-Suche im Find-Feld mit
\nfür Zeilenumbrüche. - Case-Modifier:
\U$1(uppercase),\L$1(lowercase),\u$1(nur erstes Zeichen) im Replace. - Suche pro Datei mit dem Lupen-Icon links; Workspace-weit mit der Such-Sidebar (dort auch Glob-Includes/-Excludes).
- Preview der Änderungen vor dem Apply — Pflicht für grosse Sweeps.
VS-Code-Regex ist im Wesentlichen der JavaScript-Dialekt: \d, \w, \s, Lookahead/Lookbehind, named captures (?<name>...), aber kein \K und keine rekursiven Pattern.
In MS Word und LibreOffice
Hier ist Vorsicht geboten — die beiden Programme implementieren völlig unterschiedliche Pattern-Sprachen:
Word (Windows/Mac) — „Wildcards”
Word hat kein echtes Regex. Das Feature heisst „Wildcards” (engl.) bzw. „Platzhalter verwenden” (de) und muss im Suchen-Dialog (Cmd-F → erweiterte Optionen → „Mit Platzhaltern suchen”) explizit aktiviert werden. Eine eigene, beschränkte Syntax:
| Word-Wildcard | Bedeutung |
|---|---|
? | beliebiges Zeichen |
* | beliebige Zeichenfolge |
[abc] | eine der Optionen |
[a-z] | Bereich |
[!abc] | Negation |
< > | Wortanfang / -ende (statt \b) |
@ | ein oder mehr des vorherigen (statt +) |
{n} {n,} {n,m} | Wiederholung |
(...) | Gruppe |
\1 \2 | Backreferenz im Ersetzen |
Beispiele Word:
Suchen: (<*>) (<*>)
Ersetzen: \2 \1
# vertauscht zwei Wörter
Suchen: [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
# findet Datum DD.MM.YYYY (ohne Capture)
Suchen: <persName>(*)</persName>
Ersetzen: \1
# entfernt Tag, behält Inhalt
Wichtige Word-Spezifika: \d und \w existieren nicht. Punkt . matcht den Punkt, nicht ein beliebiges Zeichen. Anker ^ und $ haben andere Bedeutung (^p = Absatzmarke, ^t = Tab). Die Quirks der Word-Syntax sind die häufigste Stolperfalle, wenn man von echten Regex herkommt.
LibreOffice — ICU-Regex
LibreOffice (Writer und Calc) nutzt echtes Regex auf Basis der ICU-Library — sehr nah an PCRE. Im Suchen-Dialog (Cmd-Alt-F) den Haken bei „Reguläre Ausdrücke” setzen.
# Datum DD.MM.YYYY → YYYY-MM-DD
Suchen: \b(\d{1,2})\.(\d{1,2})\.(\d{4})\b
Ersetzen: $3-$2-$1
# Mehrere Leerzeichen zu einem
Suchen: \s{2,}
Ersetzen: (ein Leerzeichen)
# Absatz-Ende-Marker (nur in Replace) als \n
# In ICU: \n in Replace = Zeilenumbruch
Wichtige LibreOffice-Spezifika:
- Backreference im Ersetzen mit
$1, nicht\1. - Newline im Suchfeld ist
\n, in Calc auch\nzwischen Spalten — Vorsicht, Calc und Writer unterscheiden sich subtil. - Lookbehind funktioniert (ICU >= 70), war früher eingeschränkt.
Dialekt-Unterschiede in der Übersicht
| Feature | grep BRE | grep ERE / ack / rg | VS Code | LibreOffice | Word |
|---|---|---|---|---|---|
+ ? {} | mit \+ etc. | direkt | direkt | direkt | @ für +, {} |
\d \w \s | nein | mit -P ja | ja | ja | nein |
| Lookaround | nein | mit -P ja | ja | ja (modern) | nein |
| Named Capture | nein | mit -P ja | ja | ja | nein |
| Capture-Backref im Replace | \1 | \1 | $1 | $1 | \1 |
| Multiline-Default | nein | nein | nein | nein | im Wildcards-Modus eingeschränkt |
| Punkt matcht Newline | nein | nein | mit (?s) flag | mit (?s) flag | (irrelevant) |
Häufige Fallen
- Greedy by default —
<.*>matcht in<a>x</a>die ganze Zeile von<abis</a>. Lazy mit<.*?>oder Negation<[^>]*>nutzen. - Punkt im Datums-Pattern —
\d{1,2}.\d{1,2}.\d{4}matcht auch12345678(Punkte als „beliebig”). Backslash-escape:\. - Anker-Bedeutung verwechselt — in Word ist
^pAbsatz, in den meisten anderen Tools ist^„Zeilenanfang”. - Backref-Notation falsch — in
sed/grep -Pmit\1, in VS Code/LibreOffice mit$1. Kopier-und-paste zwischen Tools sorgt regelmässig für Frust. - Encoding — Regex auf Latin-1-Datei kann mit
\wUmlaute nicht matchen; UTF-8 + Unicode-Flag (-uin ripgrep) löst es. - Multiline-Verhalten — defaultmässig matcht
.keinen Newline.(?s)-Flag oder explizit[\s\S]als „wirklich alles”. - Catastrophic Backtracking — verschachtelte unbeschränkte Quantifizierer (
(a+)+b) können bei Grossdateien minutenlang hängen. Im Zweifel possessiv ((a++)+bin PCRE) oder Pattern umschreiben. - Vor dem produktiven Replace immer „Find only” — eine schlecht formulierte Regex zerstört in Sekunden Hunderte Dateien.
- Word-Wildcards sind nicht Regex — wer
\din Word eingibt, sucht nach dem Backslash gefolgt von „d”.
Werkzeuge zum Üben und Debuggen
- regex101.com — interaktiver Tester mit Erklärung jedes Tokens, Flavor-Auswahl (PCRE, JS, .NET, Python, Go, Java)
- regexr.com — alternativer Tester mit Cheat-Sheet
- VS Code „Regex Preview”-Extension — zeigt Treffer im Editor live
pcregrep/pcre2grep— wenngrep -Pim System fehltripgrep --debug— zeigt, wie das Pattern intern interpretiert wird
Lektüre-Empfehlung
Jeffrey E. F. Friedl, Mastering Regular Expressions (3. Aufl., O’Reilly 2006). Die kanonische Referenz. Friedl erklärt nicht nur die Syntax, sondern auch wie die Engine intern arbeitet — Backtracking, NFA vs. DFA, Performance-Eigenschaften. Wer regelmässig Regex auf grossen Texten betreibt, spart sich nach diesem Buch viele „warum braucht das jetzt zehn Sekunden”-Momente. Pflichtlektüre für alle, die über Copy-und-Paste hinaus arbeiten wollen.
Verhältnis zu anderen Werkzeugen
- Pandoc — kann via Lua-Filter Regex-Substitutionen während der Konversion machen
- Git —
git grepnutzt POSIX BRE, mit-EERE oder-PPCRE - OpenRefine — GREL-Funktionen wie
replace(value, /regex/, "...")mit JS-Regex-Syntax xmlstarlet— kombiniert mit Regex für XML-Massen-Edit (kombinieren mit XPath)
Links
- regex101 — Tester
- regexr — Tester
- ripgrep — User Guide
- VS Code — Regex in Search
- LibreOffice — Liste der regulären Ausdrücke
- Microsoft — Suchen mit Platzhaltern in Word
- Jeffrey E. F. Friedl: Mastering Regular Expressions, 3rd ed., O’Reilly 2006 — die Standardreferenz, siehe Lektüre-Empfehlung oben