EMZETT.
Login

Kurz: Die Stärke der Shell sind die kleinen Textprogramme, die du mit Pipes kombinierst. Wir arbeiten mit einer kleinen Beispieldatei:

Teil des Kurses Bash

Kapitel 8 von 13 im Kurs Bash. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Die Textwerkzeuge

Die Stärke der Shell sind die kleinen Textprogramme, die du mit Pipes kombinierst. Wir arbeiten mit einer kleinen Beispieldatei:

cat > log.txt <<'EOF'
2025-03-01 INFO  Server gestartet
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-02 INFO  Nutzer mia angemeldet
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
2025-03-03 INFO  Nutzer tom angemeldet
EOF
wc -l log.txt
head -n 2 log.txt
tail -n 1 log.txt

Ausgabe:

6 log.txt
2025-03-01 INFO  Server gestartet
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-03 INFO  Nutzer tom angemeldet

grep: suchen

cat > log.txt <<'EOF'
2025-03-01 INFO  Server gestartet
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-02 INFO  Nutzer mia angemeldet
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
2025-03-03 INFO  Nutzer tom angemeldet
EOF
grep ERROR log.txt                  # Zeilen mit ERROR
grep -c INFO log.txt                # zählen
grep -v INFO log.txt                # alles außer INFO
grep -i "nutzer" log.txt            # Groß-/Kleinschreibung egal
grep -n WARN log.txt                # mit Zeilennummer
grep -E "ERROR|WARN" log.txt        # erweiterte Regex (oder)
grep -o "Nutzer [a-z]*" log.txt     # nur den Treffer
grep -w "mia" log.txt               # ganzes Wort
grep -E "^2025-03-0[12]" log.txt | wc -l
grep -A1 "WARN" log.txt             # eine Zeile danach
grep -q "ERROR" log.txt && echo "Fehler im Log"

Ausgabe:

2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-03 ERROR Zeitüberschreitung bei /api/data
3
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
2025-03-02 INFO  Nutzer mia angemeldet
2025-03-03 INFO  Nutzer tom angemeldet
4:2025-03-02 WARN  Speicher knapp
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
Nutzer mia
Nutzer tom
2025-03-02 INFO  Nutzer mia angemeldet
4
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
Fehler im Log

Weitere Optionen: -r (rekursiv in Ordnern), -l (nur Dateinamen), -F (fester Text statt Regex), -P (Perl-Regex, wo verfügbar).

sed: Text umformen

sed (stream editor) bearbeitet Text zeilenweise, am häufigsten mit s/alt/neu/:

echo "Hallo Welt, Hallo Bash" | sed 's/Hallo/Hi/'       # erstes pro Zeile
echo "Hallo Welt, Hallo Bash" | sed 's/Hallo/Hi/g'      # alle
echo "a/b/c" | sed 's|/|-|g'                             # anderes Trennzeichen
echo "2025-03-15" | sed -E 's/([0-9]+)-([0-9]+)-([0-9]+)/\3.\2.\1/'
printf "eins\nzwei\ndrei\nvier\n" | sed -n '2,3p'        # nur Zeilen 2 bis 3
printf "eins\nzwei\ndrei\n" | sed '/zwei/d'              # Zeilen löschen
printf "  Text  \n" | sed 's/^ *//; s/ *$//' | sed 's/.*/[&]/'
printf "a\nb\n" | sed 's/^/> /'
printf "eins\nzwei\n" | sed '1i Kopfzeile'
printf "x=1\ny=2\n" | sed 's/=.*//'

Ausgabe:

Hi Welt, Hallo Bash
Hi Welt, Hi Bash
a-b-c
15.03.2025
zwei
drei
eins
drei
[Text]
> a
> b
Kopfzeile
eins
zwei
x
y

Mit sed -i 's/alt/neu/g' datei änderst du die Datei direkt (zur Sicherheit sed -i.bak ...).

cut, sort, uniq, tr, wc

printf "mia:17:Berlin\ntom:25:Hamburg\nzoe:31:Berlin\n" > leute.txt
cut -d: -f1 leute.txt                      # Spalte 1
cut -d: -f2,3 leute.txt
cut -c1-3 leute.txt                        # Zeichen 1 bis 3
sort -t: -k2 -n leute.txt                  # nach Spalte 2 numerisch
sort -t: -k3 leute.txt | cut -d: -f3 | uniq -c
printf "b\na\nb\nc\na\n" | sort | uniq             # Duplikate zusammenfassen
printf "b\na\nb\nc\na\n" | sort | uniq -d          # nur Duplikate
printf "b\na\nb\n" | sort -u
echo "Hallo" | tr 'a-z' 'A-Z'
echo "a,b;c" | tr ',;' '  '
echo "aabbcc" | tr -s 'a-c'                         # Wiederholungen zusammenziehen
echo "geheim123" | tr -d '0-9'
wc -l -w -c <<< "drei kleine Wörter"
paste -sd, <<< $'1\n2\n3'
sort -r <<< $'a\nc\nb'
sort -h <<< $'10K\n2M\n500'
tac <<< $'1\n2\n3'

Ausgabe:

mia
tom
zoe
17:Berlin
25:Hamburg
31:Berlin
mia
tom
zoe
mia:17:Berlin
tom:25:Hamburg
zoe:31:Berlin
      2 Berlin
      1 Hamburg
a
b
c
a
b
a
b
HALLO
a b c
abc
geheim
      1       3      20
1,2,3
c
b
a
500
10K
2M
3
2
1

awk: Spalten und Berechnungen

awk liest Zeilen, teilt sie in Felder ($1, $2 …) und führt Aktionen aus: awk 'Muster { Aktion }'.

printf "Mia 17 Berlin\nTom 25 Hamburg\nZoe 31 Berlin\nBen 9 Köln\n" > p.txt
awk '{ print $1 }' p.txt                           # erste Spalte
awk '{ print $3, $1 }' p.txt                       # umsortiert
awk '$2 >= 18 { print $1 " ist volljährig" }' p.txt
awk '$3 == "Berlin"' p.txt
awk '{ summe += $2 } END { print "Summe:", summe, "Mittel:", summe / NR }' p.txt
awk '{ n[$3]++ } END { for (s in n) print s, n[s] }' p.txt | sort
awk 'NR % 2 == 0' p.txt                            # jede zweite Zeile
awk -F: '{ print $1 }' <<< "root:x:0"              # anderes Trennzeichen
awk '{ printf "%-5s|%3d|\n", $1, $2 }' p.txt
awk 'length($1) == 3 && /e/ { print NR": "$0 }' p.txt

Ausgabe:

Mia
Tom
Zoe
Ben
Berlin Mia
Hamburg Tom
Berlin Zoe
Köln Ben
Tom ist volljährig
Zoe ist volljährig
Mia 17 Berlin
Zoe 31 Berlin
Summe: 82 Mittel: 20.5
Berlin 2
Hamburg 1
Köln 1
Tom 25 Hamburg
Ben 9 Köln
root
Mia  | 17|
Tom  | 25|
Zoe  | 31|
Ben  |  9|
1: Mia 17 Berlin
3: Zoe 31 Berlin
4: Ben 9 Köln

Nützliche awk-Variablen: NR (Zeilennummer), NF (Feldanzahl), $0 (ganze Zeile), FS/OFS (Trennzeichen).

find und xargs

cd "$(mktemp -d)"
mkdir -p src/lib docs
touch src/main.c src/lib/util.c src/lib/util.h docs/readme.md notiz.txt
find . -name "*.c" | sort
find . -type d | sort
find . -type f -name "*.h" -o -name "*.md" | sort
find . -maxdepth 1 -type f
find src -name "*.c" -exec basename {} \; | sort
find . -type f -empty | wc -l
find . -name "*.c" -print0 | xargs -0 -n1 basename | sort

Ausgabe:

./src/lib/util.c
./src/main.c
.
./docs
./src
./src/lib
./docs/readme.md
./src/lib/util.h
./notiz.txt
main.c
util.c
5
main.c
util.c

Praxisbeispiel: Log auswerten

cat > log.txt <<'EOF'
2025-03-01 INFO  Server gestartet
2025-03-01 ERROR Datenbank nicht erreichbar
2025-03-02 INFO  Nutzer mia angemeldet
2025-03-02 WARN  Speicher knapp
2025-03-03 ERROR Zeitüberschreitung bei /api/data
2025-03-03 INFO  Nutzer tom angemeldet
EOF
echo "Meldungen pro Stufe:"
awk '{ print $2 }' log.txt | sort | uniq -c | sort -rn
echo "Fehler pro Tag:"
grep ERROR log.txt | cut -d' ' -f1 | sort | uniq -c
echo "Angemeldete Nutzer:"
grep -o 'Nutzer [a-z]*' log.txt | cut -d' ' -f2 | paste -sd,

Ausgabe:

Meldungen pro Stufe:
      3 INFO
      2 ERROR
      1 WARN
Fehler pro Tag:
      1 2025-03-01
      1 2025-03-03
Angemeldete Nutzer:
mia,tom

Merke

  • grep sucht (-i -v -n -c -E -o -r), sed ersetzt (s/a/b/g), awk rechnet mit Spalten
  • cut, sort, uniq -c, tr, wc, head, tail, paste als Bausteine
  • find ... -exec / xargs wenden Befehle auf Dateien an
  • Pipes kombinieren alles zu kleinen Auswertungen

Übungsaufgabe

Finde in einer Beispiel-Logdatei die 3 häufigsten IP-Adressen (awk, sort, uniq -c, head).

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Pipes, Umleitungen und Prozesse

Weiter: Dateisystem, Navigation und Rechte

Alle Kapitel: Bash im Überblick