cli.help: RegEx, grep und sed – Text-Tools ftw!
Ihr wollt etwas wirklich Mächtiges haben? Reguläre Ausdrücke!
Grep und sed sind die Standardwerkzeuge zum Suchen in und Bearbeiten von Textdateien - mit Möglichkeiten, von denen Word & Co. nur träumen können. Ohne reguläre Ausdrücke, kurz RegEx, ist das aber nur der halbe Spaß. Aber die Mistdinger kann man sich verdammt schlecht merken - daher unser Cheat Sheet für den Terminal.
cli.help
Zur Erinnerung: cli.help liefert Euch die Hilfe zu Terminal-Befehlen direkt im Terminal, auf Deutsch, abzufragen via curl - etwa:
curl cli.help/hilfe
curl cli.help/tools
Und wenn Ihr einfach mal alles durchsuchen wollt:
curl cli.help/alles | grep irgendwas
Textgötter
Wer in Textdateien, Ausgaben von Befehlen, Logs und sonstigen Buchstabenhaufen etwas sucht, tut das im Terminal mit dem Standard-Tool grep - die Windows-Suche ist ein Fliegenschiss dagegen. Warum? Weil Ihr mit RegExes arbeiten könnt. Das sind Konstrukte, die Zeichenketten genau beschreiben - eine ausführliche (und nun wirklich nicht staubtrockene) Einführung liefert Euch Captain RegEx persönlich. Mal als Teaser/Kurzversion: Wenn Euer Mediencenter, etwa Kodi, eine Datei tbbt_s03e20.mkv als "The Big Bang Theory - Staffel 3, Episode 20" erkennt, dann via RegEx.
sed ist sicherlich etwas weniger häufig im Einsatz, aber kaum ein Admin oder Programmierer kommt ohne aus - und Ihr auch nicht mehr, wenn Ihr es einmal kennt ;) Mit sed könnt Ihr zum Beispiel eine eigene Markup-Sprache basteln oder auch nur Eure Lieblingsrechtschreibfeeler in 1.000 Dokumenten auf einmal korrigieren.
Und wie immer bei cli.help-Update, hier pro forma noch die lieblos heruntergedaddelten Inhalte - die Ihr freilich so abrufen solltet:
curl cli.help/sed
curl cli.help/regex
curl cli.help/grep
regex
Übersicht
Übersicht WICHTIGER RegEx-Anweisungen. Je nachdem wo sie genutzt werden, kann die Syntax leicht abweichen, da PHP, Perl und andere Tools eigene Dialekte verwenden. Üblich sind neben "normalen" Ausdrücken auch POSIX-/erweiterte Varianten, etwa [:lower:] statt [a-z] - einige werden hier mit aufgeführt. Hier drei mal das Gleiche:
[:word:] Ganzes Wort
\w Ganzes Wort
[[:alnum:]_] Ganzes Wort - in der Praxis immer doppelte Klammern,
da mehrere Klassen kombiniert werden können.
Im Zweifelsfall schaut bei regex101.com vorbei.
Beispiele folgen unten.
Top 10
. Beliebiges Zeichen
* 0 oder mehr
'a|b' a ODER b
\n Zeilenumbruch
\t Tab
\d Ziffern - als POSIX-Variante: [:digit:]
^ Anfang der Zeile
$ Ende der Zeile
(hallo)(welt) hallo als Matchgruppe $1, welt als $2
\QIch\.*bin\E Wörtlich: "Ich\.*bin"
Anker
^ Anfang der Zeile
$ Ende der Zeile
\b Ganzes Wort
\< Wortanfang
\> Wortende
Zeichenklassen
\s Whitespace
[:space:] Whitespace
\S Nicht-Whitespace
\d Ziffer
\D Keine Ziffer
\w Ganzes Wort
\W Kein Wort
[A-Z] Großbuchstaben
[:upper:] Großbuchstaben
[a-z] Kleinbuchstaben
[:lower:] Kleinbuchstaben
[:alpha:] Groß- und Kleinbuchstaben
[A-Za-z] Groß- und Kleinbuchstaben
[0-9] Ziffern
[:digit:] Ziffern
[0-9A-Za-z] Ziffern und Buchstaben
[:alnum:] Ziffern und Buchstaben
[ \t] Space und TAB
[:blank:] Space und TAB
Quantifizierer
* 0 oder mehr
+ 1 oder mehr
? 0 oder 1
{4} 4
{4,} 4 oder mehr
{4,7} 4 bis 7
Sonderzeichen
\n New-Line-Zeilenumbruch
\r Carriage-return-Zeilenumbruch
\t Tab
\v Vertikaler Tab
Lookarounds, Conditionals
(?!) Negative Lookahead
(?<!) Negative Lookbehind
(?=) Positive Lookahead
(?<=) Positive Lookbehind
(?(?<=if.)then|else) Matcht THEN nach "if " und ELSE nach allem außer "if ".
(if.)?(?(1)then|else) Matcht IF THEN oder ELSE
Ja, der Abschnitt ist verwirrend ;)
Beispiele mit grep und sed
Je nach Tool sehen die RegExes anders aus - und selbst einzelne Tools funktionieren teils je nach Version leicht bis deutlich unterschiedlich ... ist leider so.
Suche nach "foo oder bar" - Standard und Perl (-P):
grep -e 'foo\|bar'
grep -eP 'foo|bar'
Suche nach foo ohne Bindestrich davor/danach:
grep -eP '(?<!-)foo(?!-)'
Suche nach IPs wie 192.168.77.1:
grep -e '(\d{1,3}\.){3}\d{1,3}'
sed: you durch me ersetzen - normal, POSIX-/erweiterte Variante (-E):
echo fuck you | sed 's/\(.*\)\(you\)/\1 me/'
echo fuck you | sed -E 's/(.*)(you)/\1 me/'
grep
(Zeilen mit) foobar in Datei text.txt suchen, Groß-Klein-Schreibung ignorieren (-i):
grep -i "foobar" < text.txt
cat text.txt | grep "foobar"
foo ODER bar per Regular Expression (-e) in allen Textdateien in allen Unterordnern (-r) suchen:
grep -er "foo|bar" *
Begriffe aus terms.txt in allen Dateien suchen:
grep -f terms.txt *
foobar in Datei text.txt suchen - plus 3 Zeilen davor (-B) und danach (-A) anzeigen:
grep -A3 -B3 "foobar" < text.txt
foobar in Datei text.txt suchen - nur Treffer ausgeben (-o), nicht Zeile:
grep -o "foobar" < text.txt
Nur die ersten 10 Treffer (-m), mit Zeilennummern (-n):
grep -m10 -n "foobar" < text.txt
Zeilen ohne foobar ausgeben (invertieren mit -v):
grep -v "foobar" < text.txt
IP-Adressen aus allen Dateien auslesen:
grep -e '(\d{1,3}\.){3}\d{1,3}' *
Suche nach foo ohne Bindestrich davor/danach per Perl-RegEx (-P):
grep -eP '(?<!-)foo(?!-)'
sed
Beispieltext für Beispiele, die aus "text.txt" lesen:
Ich sage moo und auch tar, das ergibt foobar - und nochmal: moo.
sed ist simpel - sieht nur kompliziert aus wegen der RegEx. Generelle Syntax für fast alles mit und ohne Match-Gruppen (g für global):
sed 's/SUCHPHRASE/ERSATZ/g'
sed 's/\(Gruppe1\)\(Gruppe2\)/Gruppe2 als Variable ist \2/g'
Erstes moo-Vorkommen pro Zeile durch foo ersetzen - in Standardausgabe und in der Datei selbst (-i):
sed 's/moo/foo/' < text.txt
sed -i 's/moo/foo/' < text.txt
moo und tar durch foo und bar ersetzen - alle Vorkommnisse (/g):
sed 's/moo/foo/g; s/tar/bar/g' < text.txt
Mehrfache Leerzeichen auf eines reduzieren:
sed 's/ */ /g'
Tabs durch Leerzeichen ersetzen:
sed 's/\t/ /g'
Alle moo-Vorkommen löschen:
sed 's/moo//g' < text.txt
Erste Zeile löschen:
sed '1d' < text.txt
Alle Zeilen außer der Ersten löschen:
sed '1!d' < text.txt
Zeilen 4 bis 8 löschen:
sed '4,8d' < text.txt
Reihenfolge der Ziffern nach "1 2 3 4" umstellen/korrigieren - sed-Syntax:
echo 3 1 4 2 | sed 's/\([[:digit:]]\) \([[:digit:]]\) \([[:digit:]]\) \([[:digit:]]\)/\2\4\1\3/'
Reihenfolge der Ziffern nach "1 2 3 4" umstellen/korrigieren - erweiterte RegEx-Syntax:
echo 3 1 4 2 | sed -E 's/([0-9]) ([0-9]) ([0-9]) ([0-9])/\2 \4 \1 \3/'
Mehr zu Terminal-Themen und zu cli.help.