Crewlove â Kapitel 30: RegulĂ€re AusdrĂŒcke (Regex)
Crewlove-Notiz: Regex ist wie eine Spur im Log-Wald: du siehst nicht alles â aber du erkennst Muster.
30.0 Was ist ein regulÀrer Ausdruck?
Ein regulĂ€rer Ausdruck (kurz Regex / RegExp) ist eine kompakte Schreibweise, um Muster in Texten zu beschreiben â zum Suchen, Filtern, Extrahieren und Ersetzen.
Du findest Regex in vielen Umgebungen:
- Python (
re) - JavaScript (
RegExp,/.../) - PHP (
preg_*) - Shell-Tools wie grep, sed, awk, perl
- Editor-Suche (VS Code, Sublime, âŠ)
30.1 Grundbegriffe â fang klein an
| Symbol | Bedeutung | Mini-Beispiel | ||
|---|---|---|---|---|
. |
beliebiges Zeichen (auĂer Zeilenumbruch) | a.c â abc, axc |
||
* |
0 oder mehr Wiederholungen | ab*c â ac, abc, abbc |
||
+ |
1 oder mehr Wiederholungen | ab+c â abc, abbc |
||
? |
0 oder 1 Wiederholung | colou?r â color, colour |
||
^ |
Start der Zeile | ^Hello |
||
$ |
Ende der Zeile | world$ |
||
[...] |
Zeichenmenge | [abc] |
||
(...) |
Gruppierung (Capture) | (\d{2})/(\d{4}) |
||
| |
ODER | cat | dog |
||
\d |
Ziffer | \d+ |
||
\w |
Wort-Zeichen | \w+ |
Tipps:
- Starte mit einem Mini-Text wie
"Hello world". - Teste live im Regex-Tester, bevor du es ins Skript packst.
30.2 Lernpfad â Schritt fĂŒr Schritt
| Stufe | Fokus |
|---|---|
| 0 | Metazeichen verstehen (.^$*+?[]()) |
| 1 | Muster fĂŒr Alltag (E-Mail, Zahlen, IDs) |
| 2 | Gruppen & Referenzen ((...), $1) |
| 3 | Lookarounds (wenn deine Engine es kann) |
| 4 | Matches im Code extrahieren (Python/JS/PHP) |
| 5 | Ăben mit echten Projekttexten (Logs/Configs/CSV) |
| 6 | Kleine Ăbungsskripte (10 Aufgaben â Routine) |
| 7 | Flags lernen (i, m, s, g, ⊠je nach Tool) |
30.3 Werkzeuge
Online-Tester
- regex101.com
- regexr.com
- debuggex.com
Merke: Nicht jede Regex-Engine kann alles.
grep -E(ERE) ist anders alsgrep -P(PCRE)awkfolgt POSIX-Regex (keine PCRE-Lookbehinds)
30.4 Mini-Ăbung: Zeilen mit ERROR aus einer Logdatei
Python
import re
with open('log.txt', encoding='utf-8') as f:
for line in f:
if re.search(r'^ERROR', line):
print(line.rstrip())
Node.js
const fs = require('fs');
const text = fs.readFileSync('log.txt', 'utf8');
text.split('\n').forEach(line => {
if (/^ERROR/.test(line)) console.log(line);
});
30.5 Greedy vs NonâGreedy
- Greedy:
.*nimmt âso viel wie möglichâ. - NonâGreedy:
.*?nimmt âso wenig wie möglichâ.
Beispiel:
<.*>frisst zu viel<.*?>stoppt frĂŒher
30.6 Regex im Terminal: grep & awk
grep Basics
grep -i '^error' datei.txt
grep ERE (Extended)
grep -E 'open|close' datei.txt
grep -E '[0-9]{3}' logfile.txt
awk filtert Zeilen mit Regex
awk '/ERROR/ {print NR ":" $0}' logfile.txt
30.7 Crumbforest-Praxis: Nginx Accesslog Pfade zÀhlen
A) PCRE-Variante (grep -P)
grep -oP '(?<=GET\s)[^\s"]+(?=\sHTTP/\d+\.\d+")' /var/log/nginx/access.log \
| awk '{ c[tolower($0)]++ } END{ for (u in c) printf "%5d %s\n", c[u], u }' \
| sort -nr
B) Nur awk (robust, ohne grep -P)
awk '
match($0, /"GET ([^ ]+) HTTP\/[0-9.]+"/, m) {
p = tolower(m[1]); c[p]++
}
END { for (p in c) printf "%5d %s\n", c[p], p }
' /var/log/nginx/access.log | sort -nr
Warum B oft besser ist:
- lÀuft auch ohne PCRE
- weniger Shell-Quoting-Probleme
- schnell fĂŒr groĂe Logs
30.8 HĂ€ufige Stolperfallen
| Stolperfalle | Kurzlösung |
|---|---|
. matcht keinen Zeilenumbruch |
Flag s/DOTALL oder [\s\S] |
Escape vergessen (. statt \.) |
Punkt immer escapen, wenn literal |
| PCRE vs POSIX verwechselt | Tool/Engine checken (grep -E vs -P) |
\b in awk |
In POSIX awk ist \b kein Word-Boundary |
30.9 Kurzantwort (3 Zeilen)
^ â Anfang einer Zeile
$ â Ende einer Zeile
.*? â beliebige Zeichen, möglichst kurz
Abschluss
Regex ist kein âDark Artâ.
Es ist ein Muster-Licht im Textwald.
Und wenn du Logs lesen kannst, kannst du auch Spuren lesen.
crewlove đŠđŠđČ
Kapitel 31: sed â der Stream-Editor
Bild: sed ist wie ein kleines Messer am Fluss: du schneidest Muster aus dem Textstrom und formst ihn neu.
31.1 Die Grundform
sed -E 's/REGEX/REPLACE/' file.txt
s///= substitution (ersetzen)- ohne
gwird nur das erste Match pro Zeile ersetzt - mit
gwerden alle Matches pro Zeile ersetzt
31.2 Sicher arbeiten: erst anschauen, dann anwenden
Nur zeigen (dry-run):
sed -E 's/foo/bar/g' file.txt | less
Nur Zeilen ausgeben, die sich Ă€ndern wĂŒrden:
sed -nE 's/foo/bar/gp' file.txt
-nunterdrĂŒckt Standard-Ausgabepdruckt nur, wenn die Ersetzung passiert ist
31.3 Klassiker: Dateiendung in einer Liste Àndern (Textliste)
sed -E 's/\.txt$/.doc/' names.txt
\.= echter Punkt$= Ende der Zeile â nur Endungen, keine inneren Treffer
31.4 Log-Politur: doppelte Spaces â ein Space
sed -E 's/[[:space:]]+/ /g' logfile.txt
31.5 Stolperstein: GNU vs BSD (macOS)
- Oft klappt auf macOS auch
sed -Egut. - GNU sed kennt ebenfalls
-E(frĂŒher oft-r).
Kapitel 32: awk â die Wald-Rechenmaschine
Bild: awk ist ein kleines Programm pro Zeile: du kannst filtern, zÀhlen, gruppieren, berichten.
32.1 Felder & Standard-Variablen
$0= ganze Zeile$1,$2, ⊠= Felder (standard: getrennt durch Spaces/Tabs)NF= Anzahl FelderNR= Zeilennummer
Beispiel: zweite Spalte ausgeben
awk '{print $2}' file.txt
CSV (Komma) lesen
awk -F',' '{print $1, $3}' data.csv
32.2 Substitution: sub vs gsub
sub(r, repl)ersetzt nur das erste Match in$0gsub(r, repl)ersetzt alle Matches
echo 'foo foo' | awk '{ sub(/foo/,"bar"); print }'
# â bar foo
32.3 ZĂ€hlen: assoziative Arrays
Wie oft kommt ein Wort in einer Datei vor?
awk '{ c[$0]++ } END { for (k in c) printf "%5d %s\n", c[k], k }' list.txt | sort -nr
32.4 Match & Gruppen: Pfade aus Nginx-Accesslog zÀhlen (awk-only)
awk '
match($0, /"GET ([^ ]+) HTTP\/[0-9.]+"/, m) {
p = tolower(m[1]); c[p]++
}
END { for (p in c) printf "%5d %s\n", c[p], p }
' /var/log/nginx/access.log | sort -nr
32.5 Mini-Report: Statuscodes zÀhlen
awk '
{ code=$9; if (code ~ /^[0-9]{3}$/) c[code]++ }
END { for (k in c) printf "%6d %s\n", c[k], k }
' /var/log/nginx/access.log | sort -nr
Kapitel 33: grep â die SpĂŒrnase
#kein #krĂŒmel #geht #verloren: grep ist die Taschenlampe im Unterholz.
33.1 Drei Modi: schnell, flexibel, mÀchtig
grep -Fâ Fixed strings (am schnellsten, keine Regex)grep -Eâ Extended Regex (ERE:+ ? | {}ohne Backslashes)grep -Pâ PCRE (Lookarounds & mehr, falls verfĂŒgbar)
33.2 HĂ€ufige Flags
| Flag | Bedeutung |
|---|---|
-n |
Zeilennummern |
-r / -R |
rekursiv (Verzeichnisse) |
-i |
ignore case |
-v |
invert (alles auĂer Treffer) |
-c |
zÀhlen |
-o |
nur Match ausgeben |
-w |
ganzes Wort |
-x |
ganze Zeile muss matchen |
-m 1 |
nach 1 Treffer stoppen |
-C 2 |
Kontext: 2 Zeilen davor/danach |
33.3 Beispiele, die du stÀndig brauchst
Fehler im Log finden (mit Kontext):
grep -nC 2 -E 'ERROR|FATAL' app.log
Alles auĂer Kommentare & leere Zeilen:
grep -vE '^[[:space:]]*(#|$)' config.conf
Nur die Pfade aus Accesslog (PCRE):
grep -oP '(?<=GET\s)[^\s"]+(?=\sHTTP/\d+\.\d+")' /var/log/nginx/access.log
Top-Pfade zĂ€hlen (grep â awk):
grep -oP '(?<=GET\s)[^\s"]+(?=\sHTTP/\d+\.\d+")' /var/log/nginx/access.log \
| awk '{ c[tolower($0)]++ } END { for (k in c) printf "%5d %s\n", c[k], k }' \
| sort -nr | head
33.4 Pro-Tipp: Erst -F, dann Regex
Wenn du nach einem fixen String suchst (z. B. "timeout"), nimm -F:
grep -nF 'timeout' app.log
Regex ist mĂ€chtiger â aber -F ist oft schneller und sicherer.
Schluss
Mit sed formst du den Fluss,
mit awk zÀhlst du die Spuren,
mit grep findest du jeden KrĂŒmel.
#kein #krĂŒmel #geht #verloren <3
crewlove đŠđŠđČ