Zum Inhalt springen

Textwerkzeuge

Konfiguration, Logdateien, Benutzerlisten, Prozesslisten: Unter Linux ist fast alles eine Textdatei oder eine Textausgabe mit einer Zeile pro Eintrag. Dazu passt ein Werkzeugkasten aus kleinen Programmen, die je eine Sache tun und über Pipes zusammenarbeiten. Man nennt sie Filter: Sie lesen Text von stdin oder aus Dateien und schreiben das Resultat nach stdout.

Als Übungsmaterial dient auf dieser Seite vor allem /etc/passwd, eine Zeile pro Benutzer, sieben Felder, getrennt durch Doppelpunkte:

root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
Befehl Zweck Wichtige Optionen
cat ganze Datei ausgeben, Dateien aneinanderhängen -n Zeilennummern
less seitenweise lesen, blättern mit Leertaste, suchen mit /, beenden mit q -N Zeilennummern
head die ersten Zeilen -n 5 fünf Zeilen
tail die letzten Zeilen -n 5, -f folgt einer wachsenden Datei
wc zählen -l Zeilen, -w Wörter, -c Bytes

Hands-on:

Terminal-Fenster
head -n 3 /etc/passwd
tail -n 2 /etc/passwd
head -n 8 /etc/passwd | tail -n 2
wc -l /etc/passwd
sudo tail -f /var/log/syslog

tail -f ist der Befehl für Logdateien: Es zeigt das Ende und wartet auf neue Zeilen. Beenden mit Ctrl+C. Die dritte Zeile zeigt, wie du einen Ausschnitt (Zeile 7 und 8) herausschneidest.

grep muster datei gibt alle Zeilen aus, die auf das Muster passen.

Option Wirkung
-i Gross- und Kleinschreibung ignorieren
-n Zeilennummer mitausgeben
-v umkehren: nur Zeilen, die nicht passen
-c nur zählen
-w nur ganze Wörter
-r rekursiv durch ein Verzeichnis
-E erweiterte reguläre Ausdrücke (+, `

Das Muster ist ein regulärer Ausdruck. Die wichtigsten Zeichen:

Zeichen Bedeutung
^ Zeilenanfang
$ Zeilenende
. ein beliebiges Zeichen
* das vorherige Zeichen null- oder mehrmals
+ das vorherige Zeichen ein- oder mehrmals (nur mit -E)
[abc], [0-9] ein Zeichen aus der Menge

Achtung, * bedeutet hier etwas anderes als beim Glob: a* passt auf «kein a, ein a, viele a». «Beliebiger Text» heisst in Regex .*. Setze Muster immer in einfache Anführungszeichen, damit die Shell nicht selbst an *, $ oder | herumbastelt.

Hands-on:

Terminal-Fenster
grep bash /etc/passwd
grep -c nologin /etc/passwd
grep -v nologin /etc/passwd
grep -n '^root' /etc/passwd
grep 'bash$' /etc/passwd
grep -i 'DAEMON' /etc/passwd
grep -E '^(root|sync):' /etc/passwd
grep -rn 'PermitRootLogin' /etc/ssh/
grep -w 'sh' /etc/passwd

Vergleiche die letzte Zeile mit grep sh /etc/passwd. -w findet nur das Wort sh, nicht bash oder ssh.

cut, sort, uniq, tr: Spalten und Zeilen bearbeiten

Abschnitt betitelt „cut, sort, uniq, tr: Spalten und Zeilen bearbeiten“
Befehl Zweck Wichtige Optionen
cut Spalten herausschneiden -d: Trennzeichen, -f1,7 Felder 1 und 7, -c1-5 Zeichen 1 bis 5
sort Zeilen sortieren -n numerisch, -r rückwärts, -k3 nach Spalte 3, -t: Trennzeichen, -u doppelte entfernen
uniq benachbarte doppelte Zeilen zusammenfassen -c mit Anzahl
tr Zeichen ersetzen oder löschen 'a-z' 'A-Z', -d löschen, -s wiederholte zusammenfassen

Hands-on:

Terminal-Fenster
cut -d: -f1 /etc/passwd
cut -d: -f1,7 /etc/passwd | head -n 5
sort -t: -k3 -n /etc/passwd | tail -n 3
cut -d: -f7 /etc/passwd | sort | uniq -c
cut -d: -f7 /etc/passwd | sort | uniq -c | sort -rn
echo "$PATH" | tr ':' '\n'
echo "hallo welt" | tr 'a-z' 'A-Z'

Die vierte Zeile ist das wichtigste Muster dieser Seite: sort | uniq -c zählt, wie oft jeder Wert vorkommt. uniq erkennt nur benachbarte Duplikate, darum muss sort davor stehen. Die fünfte Zeile sortiert dann noch nach Häufigkeit.

sed ist ein Stream-Editor. Du brauchst davon vor allem einen Befehl, s/alt/neu/:

Terminal-Fenster
echo "Hallo Welt" | sed 's/Welt/Linux/'
sed 's/:x:/:PASSWORT:/' /etc/passwd | head -n 3
sed -n '1,3p' /etc/passwd
sed -n '/bash$/p' /etc/passwd
cut -d: -f7 /etc/passwd | sed 's#/usr/sbin/nologin#kein Login#'

s/alt/neu/ ersetzt pro Zeile das erste Vorkommen, mit s/alt/neu/g alle. -n zusammen mit p gibt nur die ausgewählten Zeilen aus, in der dritten Zeile die Zeilen 1 bis 3, in der vierten die Zeilen mit Treffer. Das Trennzeichen muss kein / sein; enthält das Muster Pfade, nimmst du # und sparst dir das Maskieren.

awk ist eine ganze Programmiersprache. Hier reicht eine Verwendung: Spalten ausgeben, egal wie viele Leerzeichen oder Tabs dazwischen stehen. Die Felder heissen $1, $2 und so weiter, $NF ist das letzte.

Terminal-Fenster
ls -l /etc | awk '{print $9}'
ls -l /etc | awk '{print $5, $9}' | sort -n | tail -n 3
awk -F: '{print $1}' /etc/passwd
awk -F: '{print $1 " nutzt " $7}' /etc/passwd | head -n 3
awk -F: '$7 == "/bin/bash" {print $1}' /etc/passwd

-F: setzt den Feldtrenner, die letzte Zeile zeigt eine Bedingung vor dem Block: Nur Zeilen, deren siebtes Feld /bin/bash ist. Das awk-Programm steht immer in einfachen Anführungszeichen, damit die Shell $1 nicht selbst ersetzt.

cut oder awk? cut ist einfacher, wenn der Trenner ein einzelnes Zeichen ist. awk gewinnt bei Leerzeichen in variabler Zahl, etwa bei der Ausgabe von ls -l, ps oder df.

date zeigt Datum und Zeit, und mit einem Format-String nach + bestimmst du die Darstellung. Die %-Platzhalter tauchen in ähnlicher Form in fast jeder Programmiersprache wieder auf.

Format Ausgabe Bedeutung
%d %m %Y 05 11 2026 Tag, Monat, Jahr vierstellig
%y 26 Jahr zweistellig
%H %M %S 19 03 58 Stunde (0 bis 23), Minute, Sekunde
%T 19:03:58 Kurzform für %H:%M:%S
%F 2026-11-05 Kurzform für %Y-%m-%d, sortierbar
%A %B Donnerstag November Wochentag und Monat ausgeschrieben, sprachabhängig
%a %b Do Nov abgekürzt
%s 1793.. Sekunden seit 1.1.1970, der Unix-Timestamp
%n Zeilenumbruch

Hands-on:

Terminal-Fenster
date
date +%F
date "+%d.%m.%Y %H:%M"
date "+%A, den %d. %B %Y"
date "+Es ist %T Uhr"
date +%s
date -d "2 weeks ago" +%F
date -d "next monday"
date -d "@1700000000"

-d rechnet mit Datumsangaben, auch in Alltagssprache. Praktisch für Backups: tar czf "backup-$(date +%F).tar.gz" ~/projekt erzeugt einen Dateinamen mit dem heutigen Datum, der sich alphabetisch richtig sortiert.

Terminal-Fenster
cp /etc/hosts /tmp/hosts
echo "10.0.0.5 testserver" >> /tmp/hosts
diff /etc/hosts /tmp/hosts
diff -u /etc/hosts /tmp/hosts

diff -u ist das Format, das du aus git diff kennst: - für entfernte, + für hinzugefügte Zeilen. Ohne Ausgabe sind die Dateien identisch.

Jetzt setzt du die Filter zusammen. Jede Pipeline löst eine konkrete Frage:

Welche Befehle benutze ich am häufigsten?

Terminal-Fenster
history | awk '{print $2}' | sort | uniq -c | sort -rn | head

history gibt Nummer und Befehl, darum $2. Dann das Zählmuster und die Top 10.

Welche Benutzer haben eine Bash als Login-Shell?

Terminal-Fenster
grep '/bin/bash$' /etc/passwd | cut -d: -f1

Welche Shells sind wie oft im Einsatz?

Terminal-Fenster
cut -d: -f7 /etc/passwd | sort | uniq -c | sort -rn

Die fünf grössten Dateien in /var/log?

Terminal-Fenster
sudo find /var/log -type f -printf '%s %p\n' | sort -rn | head -n 5

Welche IP-Adressen tauchen in einem Log am häufigsten auf?

Terminal-Fenster
sudo grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/auth.log | sort | uniq -c | sort -rn | head

-o gibt nur den Treffer aus statt der ganzen Zeile. Das Muster beschreibt vier Zahlengruppen mit Punkten dazwischen. Auf einem Server mit SSH-Zugang aus dem Internet ist das eine ernüchternde Liste. Fehlt /var/log/auth.log auf deiner VM (ohne rsyslog schreibt Ubuntu nur ins Journal), nimm journalctl -u ssh --no-pager als ersten Befehl der Pipeline, dasselbe gilt für tail -f /var/log/syslog weiter oben (journalctl -f).

Lösung anzeigen
pipelines.sh
#!/bin/bash
#
# pipelines.sh - fünf Beispiel-Pipelines zu Modul 7
echo "== 1. Häufigste Befehle =="
grep -v '^#' ~/.bash_history | awk '{print $1}' | sort | uniq -c | sort -rn | head
echo "== 2. Benutzer mit UID ab 1000 =="
awk -F: '$3 >= 1000 {print $1}' /etc/passwd | sort
echo "== 3. Dateiendungen in /etc =="
find /etc -maxdepth 1 -type f | grep '\.' | sed 's/.*\.//' | sort | uniq -c | sort -rn
echo "== 4. Grösste Verzeichnisse unter /usr =="
du -s /usr/* 2>/dev/null | sort -rn | head -n 3
echo "== 5. Zeitstempel =="
echo "Dieses Skript lief am $(date +%d.%m.%Y) um $(date +%H:%M)"

Selbstcheck · 6 Fragen

1. Warum steht vor `uniq -c` fast immer ein `sort`?
2. Was bedeutet `*` in einem regulären Ausdruck?
3. Welcher Befehl gibt das siebte Feld von /etc/passwd aus? (mehrere Antworten möglich)
4. Was ist an `sed -i` gefährlich?
5. Was gibt `date +%F` aus?
6. Was macht `grep -v`?