Linux im Griff

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.

Mirco Lang

Freier Journalist, Exil-Sauerländer, (ziemlich alter) Skateboarder, Dipl.-Inf.-Wirt, Einzelhandelskaufmann, Open-Source-Nerd, Checkmk-Handbuchschreiber. Ex-Saturn'ler, Ex-Data-Becker'ler, Ex-BSI'ler. Computer-Erstkontakt: ca. 1982 - der C64 des großen Bruders eines Freunds. Wenn Ihr hier mehr über Open Source, Linux und Bastelkram lesen und Tutonaut unterstützen möchtet: Über Kaffeesponsoring via Paypal.freue ich mich immer. Schon mal im Voraus: Danke! Nicht verpassen: cli.help und VoltAmpereWatt.de. Neu: Mastodon

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Schaltfläche "Zurück zum Anfang"