8 Standardkanäle und Filterkommandos
8 Standardkanäle und Filterkommandos
Lernziele
-
Die Ein und Ausgabeumlenkung der Shell beherrschen
-
Die wichtigsten Filterkommandos kennen
Vorkenntnisse
-
Arbeit mit der Shell
-
Umgang mit einem Texteditor (Kapitel 3)
-
Umgang mit Dateien und Verzeichnissen (Kapitel 6)
Tabelle 8.1: Standardkanäle unter Linux
| Kanal | Bezeichnung | Kürzel | Gerät | Zweck |
|---|---|---|---|---|
| 0 | Standard-Eingabe | stdin | Tastatur | Programme erhalten Eingaben |
| 1 | Standard-Ausgabe | stdout | Bildschirm | Programme senden Ausgaben |
| 2 | Standard-Fehlerausgabe | stderr | Bildschirm | Programme senden Fehlermeldungen |
8.1 Ein-/Ausgabeumlenkung und Kommandopipelines
8.1.1 Die Standardkanäle
Viele Linux-Kommandos – beispielsweise grep & Co. aus Kapitel 7 – sind so aufgebaut, dass sie Eingabedaten lesen, diese manipulieren und das Ergebnis dieser Manipulationen ausgeben. Wenn Sie beispielsweise einfach „$ grep xyz-” eingeben, können Sie anschließend Textzeilen auf der Tastatur eingeben. grep wird dann nur diejenigen durchlassen, die die Zeichenfolge „xyz” enthalten.
$ grep xyz abc def
xyz 123
xyz 123 aaa bbb YYYxyzZZZ YYYxyzZZZ Strg + d
(Die Tastenkombination am Schluss signalisiert grep, dass die Eingabe beendet ist.)
Grep liest Daten von der „Standard-Eingabe“ – in diesem Fall die Tastatur – und schreibt sie auf die „Standard-Ausgabe“ – in diesem Fall den Konsolenbildschirm oder, wahrscheinlicher, ein Terminalprogramm in einer grafischen Arbeitsumgebung. Als dritten dieser „Standardkanäle” gibt es noch die „Standard-Fehlerausgabe”. Während auf die Standard-Ausgabe die „Nutzdaten” geschrieben werden, die grep produziert, landen auf dieser allfällige Fehlermeldungen (etwa weil eine Eingabedatei nicht existiert oder der reguläre Ausdruck einen Syntaxfehler enthält).
In diesem Kapitel lernen Sie, wie Sie die Standardausgabe eines Programms beispielsweise in eine Datei umlenken oder die Standardsitzung einer Datei entnehmen können. Noch wichtiger ist, dass Sie lernen werden, wie Sie die Ausgabe eines Programms direkt (ohne Umweg über eine Datei) als Eingabe an ein anderes Programm weiterleiten können. Dies eröffnet Ihnen die Möglichkeit, die für sich genommen alle recht simplen Linux-Kommandos im Baukastenprinzip zu Anwendungen zu verketten, die sehr komplexe Dinge tun können.
💡 Dieses Thema werden wir in diesem Kapitel nicht erschöpfend behandeln können. Freuen Sie sich auf die Linux-Front-Schulungsunterlage „Linux für Fortgeschrittene”, in der die Erstellung von Shellskripten mit den Kommandos des Linux-Baukastens eine sehr wichtige Rolle spielt! Hier lernen Sie jedoch die Grundlagen, um bereits auf der Kommandozeile Linux-Kommandos geschickt zu kombinieren.
Die Standardkanäle werden in Bild 8.1 noch einmal zusammengefasst. Im Jargon werden sie meist nur mit den englischen Kürzeln stdin, stdout und stderr für Standard-Eingabe, Standard-Ausgabe und Standard-Fehlerausgabe benannt.
Bild 8.1: Standardkanäle unter Linux
Diesen Kanälen sind die Nummern 0, 1 und 2 zugeordnet. Das werden wir gleich noch brauchen.
Die Shell kann diese Standardkanäle für einzelne Kommandos auf andere Ziele umleiten, ohne dass die betroffenen Programme davon etwas mitbekommen. Diese benutzen immer die Standardkanäle. Lediglich die Ausgabedaten gelangen dann gegebenenfalls nicht mehr auf den Bildschirm bzw. ins Terminal-Fenster, sondern in eine beliebige andere Datei. Das kann ein anderes Gerät sein, etwa der Drucker. Es ist aber auch möglich, eine Textdatei anzugeben, in der die Ausgabedaten abgelegt werden sollen. Diese muss nicht einmal vorher existieren, sondern wird bei Bedarf neu erzeugt.
Auf die gleiche Art und Weise können Sie auch den Standard-Eingabekanal umleiten. Ein Programm erhält seine Informationen dann nicht von der Tastatur, sondern entnimmt sie der angegebenen Datei. Diese kann entweder für ein Gerät stehen oder eine Datei im eigentlichen Sinne sein.
💡 Sie können die Tastatur und den Bildschirm des „Terminals“, an dem Sie arbeiten, über die Datei /dev/tty ansprechen. Dabei ist es egal, ob es sich um die Textkonsole eines Linux-Rechners, ein „echtes“ seriell angeschlossenes Terminal, ein Terminalfenster in einer grafischen Umgebung oder eine Sitzung über das Netz, etwa mit der Secure Shell, handelt. Wenn Sie Daten lesen wollen, betrifft dies die Tastatur. Bei der Ausgabe betrifft es den Bildschirm (umgekehrt wäre ziemlich albern). Der Aufruf
$ grep xyz /dev/tty
Dies wäre zum Beispiel äquivalent zu unserem Beispiel weiter oben in diesem Abschnitt. Mehr über solche „besonderen Dateien” erfahren Sie in Kapitel 10.
8.1.2 Standardkanäle umleiten
Den Standardausgabekanal können Sie mit dem Operator »>«, also dem »Größer-als«-Zeichen, umleiten. Im folgenden Beispiel wird die Ausgabe von „ls -laF” in eine Datei namens „inhalt” umgeleitet; auf dem Bildschirm erscheint dabei lediglich
$ ls -laF >inhalt
$ _
Wenn die Datei „Inhalt” noch nicht existiert, wird sie neu angelegt. Sollte hingegen bereits eine Datei mit diesem Namen vorhanden sein, wird deren Inhalt überschrieben. Die Shell erledigt dies, noch bevor das gewünschte Programm überhaupt gestartet wird. Das bedeutet, dass die Ausgabedatei auch dann angelegt wird, wenn der eigentliche Programmaufruf falsch eingetippt wurde oder das Programm überhaupt keine Ausgabe liefert (die Datei „inhalt” ist dann anschließend leer).
💡 Wenn Sie verhindern wollen, dass die Shell-Ausgabeumlenkung schon existierende Dateien leert, können Sie in der Bash das Kommando „set -o noclobber” eingeben. In diesem Fall bleibt eine bereits vorhandene Datei, die Ziel einer Ausgabeumlenkung ist, unverändert. Stattdessen erscheint eine Fehlermeldung.
Die Textdatei „inhalt” können Sie nun wie üblich anschauen, z. B. mit „less”:
$ less inhalt
total 7
drwxr-xr-x 12 hugo users 1024 Aug 26 18:55 /
drwxr-xr-x 5 root root 1024 Aug 13 12:52 ./
drwxr-xr-x 3 hugo users 1024 Aug 20 12:30 fotos/
-rw-r--r-- 1 hugo users 0 Sep 6 13:50 inhalt
-rw-r--r-- 1 hugo users 15811 Aug 13 12:33 pingu.gif
-rw-r--r-- 1 hugo users 14373 Aug 13 12:33 hobby.txt
-rw-r--r-- 2 hugo users 3316 Aug 20 15:14 chemie.txt
Betrachten Sie den Inhalt von „inhalt” genauer: Sie sehen einen Verzeichniseintrag mit der Dateigröße 0. Das liegt an der Arbeitsweise der Shell: Bei der Bearbeitung der Kommandozeile wird zunächst die Ausgabeumlenkung erkannt und eine neue Datei „inhalt” angelegt bzw. deren Inhalt gelöscht. Danach führt die Shell das Kommando aus, in diesem Fall ls, wobei sie die Standardausgabe von ls mit der Datei „inhalt” statt dem Bildschirm verbindet.
💡 Die Datei hat in der ls-Ausgabe die Länge 0, weil das ls-Kommando die Dateiinformationen für „inhalt” abgerufen hat, bevor tatsächlich etwas in die Datei geschrieben wurde – obwohl vor dem betreffenden Eintrag eigentlich drei andere Zeilen stehen! Das liegt daran, dass ls erst sämtliche Verzeichniseinträge liest, sie alphabetisch sortiert und erst dann mit der Ausgabe beginnt. ls sieht also die von der Shell neu angelegte oder gerade geleerte Datei „inhalt” ohne Inhalt.
Wenn Sie die Ausgabe eines Programms ans Ende einer bestehenden Datei anhängen wollen, ohne dass deren bisheriger Inhalt ersetzt wird, können Sie den Operator >> benutzen. Wenn diese Datei noch nicht existiert, wird sie auch hier neu angelegt.
$ date >> inhalt
$ less inhalt
total 7
drwxr-xr-x 12 hugo users 1024 Aug 26 18:55 /
drwxr-xr-x 5 root root 1024 Aug 13 12:52 ./
drwxr-xr-x 3 hugo users 1024 Aug 20 12:30 fotos/
-rw-r--r-- 1 hugo users 0 Sep 6 13:50 inhalt
-rw-r--r-- 1 hugo users 15811 Aug 13 12:33 pingu.gif
-rw-r--r-- 1 hugo users 14373 Aug 13 12:33 hobby.txt
-rw-r--r-- 2 hugo users 3316 Aug 20 15:14 chemie.txt
Wed Oct 22 12:31:29 CEST 2003
Im Beispiel wurde das aktuelle Datum ans Ende der Datei „inhalt” angefügt.
Eine andere Möglichkeit, die Standardausgabe eines Programms umzuleiten, bieten die „verkehrten” Anführungszeichen …. Dies wird auch als Kommandosubstitution bezeichnet: Die Standardausgabe eines Kommandos, das in verkehrten Anführungszeichen steht, wird anstelle des Kommandoaufrufs in die Befehlszeile eingebaut. Ausgeführt wird dann das, was sich durch diese Ersetzung ergibt. Ein Beispiel:
$ cat termine Unser kleiner Terminkalender
22.12. Geschenke besorgen
23.12. Christbaum besorgen
24.12. Heiligabend
$ date +%d.%m. Welches Datum haben wir?
23.12.
$ grep ^`date +%d.%m.` termine Was liegt an?
23.12. Christbaum besorgen
💡 Eine unter Umständen bequemere Syntax für date wird von modernen Shells wie der Bash unterstützt und lautet „$(date)”. Damit ist es einfacher möglich, solche Aufrufe zu verschachteln.
Mit dem „Kleiner-als“-Zeichen (<) können Sie den Standard-Eingabekanal umleiten. Nun wird statt der Tastatureingabe der Inhalt der angegebenen Datei ausgewertet.
$ wc -w <frosch.txt
1255
Im Beispiel zählt das Filterkommando wc die in der Datei frosch.txt vorkommenden Wörter.
💡 Es gibt keinen Umleitungsoperator, mit dem Sie mehrere Eingabedateien verketten können. Wenn Sie den Inhalt mehrerer Dateien als Eingabe an ein Kommando leiten wollen, müssen Sie cat benutzen:
$ cat datei1 datei2 datei3 | wc -w
(Zum „|“-Operator steht mehr im nächsten Abschnitt.) Die meisten Programme akzeptieren einen oder mehrere Dateinamen als Argumente auf der Kommandozeile.
Selbstverständlich ist auch die kombinierte Umleitung von Standard-Ein- und -Ausgabe zulässig. Die Ausgabe des Wortzähl-Beispiels wird hier in eine Datei namens „wortzahl” geschrieben.
$ wc -w <frosch.txt >wortzahl
$ cat wortzahl
1255
Neben den Standard-Eingabe- und -Ausgabe-Kanälen gibt es noch den Standard-Fehler-Kanal. Sollte ein Programm während seiner Arbeit auf Probleme stoßen, werden die zugehörigen Fehlermeldungen über diesen Kanal ausgegeben. So werden sie auch dann angezeigt, wenn die Standardausgabe in eine Datei umgeleitet wird. Wenn Sie auch die Standardfehlerausgabe in eine Datei umleiten möchten, müssen Sie beim Umleitungsoperator die Kanalnummer angeben. Bei stdin (0<) und stdout (1>) ist diese Angabe optional, bei stderr (2>) jedoch zwingend erforderlich.
Mit dem Operator >& können Sie einen Kanal in einen anderen umleiten.
make >make.log 2>&1
leitet die Standardausgabe und die Standardfehlerausgabe des Kommandos „make” in die Datei „make.log” um.
💡 Achtung: Hier kommt es auf die Reihenfolge an! Die beiden Kommandos
make >make.log 2>&1 make 2>&1 >make.log
führt zu sehr unterschiedlichen Resultaten. Im zweiten Fall wird zunächst die Standard-Fehlerausgabe dorthin geleitet, wohin auch die Standard-Ausgabe geht (standardmäßig /dev/tty), und anschließend die Standard-Ausgabe in die Datei make.log geschickt. Dies hat jedoch keinen Einfluss auf das Ziel der Standard-Fehlerausgabe.
Übungen
✏️ 8.1 [2] Mit der Option -U können Sie das Kommando ls dazu bringen, die Verzeichniseinträge unsortiert auszugeben. Trotzdem hat der Eintrag für „inhalt” in der Ausgabedatei nach dem Kommando „ls -laU >inhalt” immer noch die Länge Null. Woran könnte das liegen?
✏️ 8.2 [!2] Vergleichen Sie die Ausgaben der Kommandos „ls /tmp” und „ls /tmp > ls-tmp.txt” (wobei wir im zweiten Fall mit „Ausgabe” den Inhalt der Datei ls-tmp.txt meinen). Fällt Ihnen etwas auf? Falls ja, wie würden Sie das Phänomen erklären?
✏️ 8.3 [!2] Warum ist es nicht möglich, eine Datei mit einem einzigen Befehl durch eine neue Version zu ersetzen, etwa mit „grep xyz datei >datei“?
✏️ 8.4 [!1] Und was ist das Problem bei „cat bla >>bla” (vorausgesetzt, bla ist eine nichtleere Datei)?
✏️ 8.5 [2] Wie würden Sie in der Shell eine Meldung ausgeben, damit sie auf der Standard-Fehlerausgabe erscheint?
8.1.3 Kommando-Pipelines
Die Ausgabeumleitung dient oft nur dazu, das Ergebnis eines Programms abzuspeichern, um es anschließend mit einem anderen Kommando weiterzubearbeiten. Diese Art der Zwischenspeicherung ist jedoch nicht nur recht umständlich, sondern Sie müssen auch daran denken, die nicht mehr benötigten Dateien wieder zu löschen. Linux bietet daher eine direkte Verknüpfung von Kommandos durch Pipes an. Die Ausgabe eines Programms wird automatisch zur Eingabe des nächsten Programms.
Die direkte Verknüpfung mehrerer Befehle zu einer solchen Kommando-Pipeline („Rohrleitung”) erfolgt mit dem Zeichen |. Statt also wie im ersten Beispiel dieses Kapitels zunächst den Verzeichnisinhalt mit dem Kommando ls -laF in eine Datei namens „inhalt” umzulenken und diese dann mit less anzusehen, können Sie diesen Vorgang auch in einem Schritt ohne Zwischenspeicherung ausführen.
$ ls -laF | less
total 7
drwxr-xr-x 12 hugo users 1024 Aug 26 18:55 /
drwxr-xr-x 5 root root 1024 Aug 13 12:52 ./
drwxr-xr-x 3 hugo users 1024 Aug 20 12:30 fotos/
-rw-r--r-- 1 hugo users 449 Sep 6 13:50 inhalt
-rw-r--r-- 1 hugo users 15811 Aug 13 12:33 pingu.gif
-rw-r--r-- 1 hugo users 14373 Aug 13 12:33 hobby.txt
-rw-r--r-- 2 hugo users 3316 Aug 20 15:14 chemie.txt
Derartige Befehlsfolgen können praktisch beliebig lang sein. Auch eine abschließende Ausgabeumleitung in eine Datei ist möglich.
$ cut -d: -f1 /etc/passwd | sort | pr -2 >userlst
Bild 8.2: Das Kommando tee
Diese Kommando-Pipeline entnimmt zunächst der Systemdatei /etc/passwd alle Benutzernamen, die in der ersten, durch „:“ getrennten Spalte stehen, sortiert sie alphabetisch und schreibt sie dann zweispaltig in die Datei userlist. Die hier benutzten Kommandos werden im Übrigen im Rest dieses Kapitels genauer beschrieben.
Manchmal ist es sinnvoll, den Datenstrom innerhalb einer Kommando-Pipeline an einer bestimmten Stelle abzuspeichern, etwa weil das Zwischenergebnis an dieser Stelle auch für andere Arbeiten von Interesse ist. Der Befehl „tee” führt eine Verzweigung des Datenstroms herbei, indem dieser verdoppelt und je ein Strom in eine Datei sowie an das nächste Kommando geleitet wird. Der Name dieses Kommandos (lautmalerisch für den Buchstaben „T”) lässt sich leicht aus Bild 8.2 herleiten – oder Sie denken an ein „T-Stück” in der „Pipeline” ...
Die Anweisung „tee” ohne Parameter legt die gewünschte Datei neu an oder überschreibt eine vorhandene. Mit der Option „-a” (engl. append, „anhängen”) lässt sich die Ausgabe an das Ende einer bestehenden Datei anfügen.
$ ls -laF | tee liste | less
total 7
drwxr-xr-x 12 hugo users 1024 Aug 26 18:55 /
drwxr-xr-x 5 root root 1024 Aug 13 12:52 ./
drwxr-xr-x 3 hugo users 1024 Aug 20 12:30 fotos/
-rw-r--r-- 1 hugo users 449 Sep 6 13:50 inhalt
-rw-r--r-- 1 hugo users 15811 Aug 13 12:33 pingu.gif
-rw-r--r-- 1 hugo users 14373 Aug 13 12:33 hobby.txt
-rw-r--r-- 2 hugo users 3316 Aug 20 15:14 chemie.txt
In diesem Beispiel wird der Inhalt des aktuellen Verzeichnisses sowohl in die Datei „liste” geschrieben als auch auf dem Bildschirm ausgegeben. (Die Datei „liste” ist in der Ausgabe von „ls” noch nicht zu sehen, da sie erst später von „tee” angelegt wird – ein Unterschied zur Ausgabeumlenkung der Shell.)
Übungen
✏️ 8.6 [!2] Wie würden Sie das Zwischenergebnis schreiben? Und zwar gleichzeitig in mehrere Dateien?
8.2 Filterkommandos
Eine der Grundlagen von Unix – und somit auch von Linux – ist das „Werkzeugkastenprinzip“. Das System verfügt über eine große Anzahl von Systemprogrammen, die jeweils eine simple Aufgabe erledigen. Diese Programme können von anderen Programmen als „Bausteine” verwendet werden. Dadurch wird den Autoren jener Programme die Entwicklung der entsprechenden Funktionalität erspart. So hat beispielsweise nicht jedes Programm eine eigene Sortierfunktion, sondern viele Programme greifen auf das Kommando sort zurück. Dieser modulare Aufbau hat mehrere Vorteile:
-
Eine Vereinfachung für die Programmierer, da sie nicht ständig neue Sortierroutinen schreiben oder zumindest in ihre Programme einbauen müssen.
-
Bei einer Fehlerkorrektur oder Optimierung von sort profitieren alle Programme, die darauf zugreifen, ebenfalls – und das ohne explizite Anpassung (meistens jedenfalls).
Tabelle 8.2: Optionen für cat (Auswahl)
| Optionen | Wirkung |
|---|---|
| -b (engl. number non-blank lines) | Nummeriert alle nichtleeren Zeilen der Ausgabe, beginnend mit 1. |
| -E (engl. end-of-line) | Zeigt am Ende jeder Zeile der Ausgabe ein $ an (gut zum Aufspüren von ansonsten nicht sichtbaren Leerzeichen). |
| -n (engl. number) | Nummeriert alle Zeilen der Ausgabe, beginnend mit 1. |
| -s (engl. squeeze) | Ersetzt Folgen von Leerzeilen durch je eine. |
| -T (engl. tabs) | Stellt Tabulatorzeichen als »^I« dar. |
| -v (engl. visible) | Macht Steuerzeichen 𝑐 als »^𝑐« und Zeichen 𝛼 mit Zeichencodes größer als 127 als »M-𝛼« sichtbar. |
| -A (engl. show all) | Äquivalent zu -vET. |
Programme, die ihre Eingabe von der Standard-Eingabe lesen und ihre Ausgabe auf die Standard-Ausgabe schreiben, werden Filterkommandos oder kurz „Filter” genannt. Ohne Eingabeumleitung lesen Filter also von der Tastatur. Um die Standard-Eingabe eines solchen Kommandos zu beenden, müssen Sie die Tastenkombination Strg + d eingeben, die der Terminaltreiber als „Datei-Ende” interpretiert.
💡 Dies gilt jedoch nur für die Eingabe von Inhalten über die Tastatur. Textdateien auf der Festplatte dürfen das Zeichen Strg + d (ASCII 4) natürlich enthalten, ohne dass das System glaubt, die Datei wäre an dieser Stelle zu Ende. Im Gegensatz dazu hat ein gewisses anderes, sehr populäres Betriebssystem traditionell etwas eigenwillige Vorstellungen von der Bedeutung des Zeichens Strg + z (ASCII 26), selbst wenn es in einer Textdatei steht.
Auch viele „gewöhnliche” Kommandos, zum Beispiel das bereits gezeigte grep, verhalten sich wie Filter, wenn Sie keine Dateinamen zur Bearbeitung angeben. Eine Auswahl der wichtigsten dieser Befehle besprechen wir im Rest des Kapitels. Einige davon sind keine waschechten Filter-Kommandos, aber für alle gilt, dass sie wichtige Bausteine von Pipelines bilden.
8.3 Dateien lesen und ausgeben
8.3.1 Textdateien ausgeben und aneinanderhängen – cat
Der Befehl „cat” (von engl. „concatenate”, „verketten”) dient eigentlich dazu, mehrere auf der Kommandozeile benannte Dateien zu einer einzigen zusammenzufügen. Wenn Sie jedoch nur einen Dateinamen als Argument übergeben, wird der Inhalt der betreffenden Datei auf der Standardausgabe ausgegeben. Wenn Sie gar keinen Dateinamen übergeben, liest Cat die Standardeingabe. Dies mag zunächst nutzlos erscheinen, doch Cat bietet über Optionen die Möglichkeit, die gelesene Eingabe mit Zeilennummern zu versehen, Zeilenenden und Sonderzeichen sichtbar zu machen oder Folgen von Leerzeilen zu einer zu komprimieren (siehe Tabelle 8.2).
💡 Es versteht sich von selbst, dass nur Textdateien eine sinnvolle Bildschirmausgabe liefern. Wenn Sie das Kommando auf andere Dateitypen, wie etwa die Binärdatei /bin/cat, anwenden, besteht zumindest auf einem Textterminal nach Ende der Ausgabe die Eingabeaufforderung sehr wahrscheinlich aus unleserlichen Zeichenkombinationen. In diesem Fall können Sie durch die blinde Eingabe von „reset” den Bildschirmzeichensatz wiederherstellen. Beim Umlenken der cat-Ausgabe in eine Datei ist das natürlich kein Problem.
💡 Der „useless use of cat award” (Preis für die überflüssige Verwendung von cat) wird an Leute verliehen, die cat benutzen, obwohl es überhaupt nicht nötig ist. In den meisten Fällen akzeptieren Kommandos Dateinamen und lesen nicht nur ihre Standardeingabe, sodass cat nicht erforderlich ist, nur um ihnen eine einzige Datei auf der Standardeingabe zu „ verfüttern”. Ein Aufruf wie „cat data.txt | grep bla” ist unnötig, wenn man genauso gut „grep bla data.txt” schreiben kann. Selbst wenn grep nur seine Standardeingabe lesen könnte, wäre grep bla <data.txt kürzer und würde keinen zusätzlichen cat-Prozess involvieren.
Übungen
✏️ 8.7 [2] Wie können Sie feststellen, ob sich in einem Verzeichnis Dateien mit „merkwürdigen” Namen befinden, beispielsweise solche mit Leerzeichen am Ende oder unsichtbaren Steuerzeichen in der Mitte?
8.3.2 Anfang und Ende von Dateien – head und tail
Mitunter interessiert Sie nur ein Teil einer Datei. Die ersten paar Zeilen, um zu überprüfen, ob es sich um die richtige Datei handelt, oder bei einer Protokolldatei vor allem die letzten Einträge. Die Kommandos „head” und „tail” liefern genau das – standardmäßig die ersten bzw. die letzten zehn Zeilen jeder Datei, deren Name sie als Argument übergeben bekommen (ersatzweise die ersten bzw. letzten zehn Zeilen der Standard-Eingabe). Mit der Option -n können Sie eine andere Anzahl von Zeilen ausgeben: „head -n 20” liefert die ersten 20 Zeilen der Standard-Eingabe und „tail -n 5 daten.txt” die letzten fünf Zeilen der Datei daten.txt.
💡 Traditionell können Sie die Anzahl n der gewünschten Zeilen auch direkt in der Form „-n” angeben. Das ist offiziell nicht mehr erlaubt, aber die Linux-Versionen von head und tail unterstützen es noch.
Mit der Option -c können Sie angeben, dass nicht Zeilen, sondern Bytes gezählt werden sollen: head -c 20 zeigt die ersten 20 Bytes der Standard-Eingabe, egal wie viele Zeilen das sind. Wenn Sie an die Zahl ein „b”, „k” oder „m” (für „Blöcke”, „Kibibyte” bzw. „Mibibyte”) anhängen, wird sie mit 512, 1024 bzw. 1048576 multipliziert.
💡 Head erlaubt außerdem den Einsatz eines Minuszeichens: „head -c -20” zeigt die gesamte Standard-Eingabe bis auf die letzten 20 Bytes.
💡 Aus Fairnessgründen kann auch tail etwas, das head nicht kann: Wenn die Zeilenzahl mit „+” anfängt, zeigt es alles ab der betreffenden Zeile.
$ tail -n +3 datei Alles ab Zeile 3
Das Programm „tail” unterstützt außerdem die wichtige Option „-f”. Damit wartet tail nach der Ausgabe des aktuellen Dateiendes und gibt später hinzukommende Daten am Dateiende aus. Dies ist besonders nützlich, um Protokolldateien zu beobachten. Wenn Sie „tail -f” mehreren Dateinamen übergeben, schreibt es vor jeder neuen Ausgabe eine Kopfzeile, die angibt, in welcher Datei neue Daten angekommen sind.
Übungen
✏️ 8.8 [!2] Wie würden Sie gezielt nur die 13. Zeile der Eingabe ausgeben?
✏️ 8.9 [3] Probieren Sie den Befehl „tail -f” aus. Legen Sie eine Datei an und rufen Sie „tail -f” für diese Datei auf. Hängen Sie dann in einem anderen Fenster bzw. auf einer anderen virtuellen Konsole mit „echo >> …” etwas an die Datei an und beobachten Sie die tail-Ausgabe. Wie sieht es aus, wenn „tail” mehrere Dateien gleichzeitig beobachtet?
✏️ 8.10 [3] Was passiert mit dem Befehl „tail -f“, wenn die beobachtete Datei kürzer wird?
✏️ 8.11 [3] Erklären Sie die Ausgabe der folgenden Kommandos
$ echo Hallo >/tmp/hallo
$ echo ""Huhu Welt"" >/tmp/hallo
wenn Sie nach dem ersten echo in einem anderen Fenster das Kommando
$ tail -f /tmp/hallo
gestartet haben.
8.4 Datenverwaltung
8.4.1 Sortierte Dateien – sort und uniq
Mit dem Befehl sort können Sie die Zeilen von Textdateien nach bestimmten Kriterien sortieren. Standardmäßig erfolgt eine aufsteigende Sortierung, also von A nach Z, anhand der ASCII-Werte1 der ersten Zeichen in einer Zeile.
Dies ist auch der Grund dafür, dass deutsche Sonderzeichen fehlerhaft einsortiert werden. So beträgt beispielsweise der ASCII-Code von „Ä” 143 und dieser Buchstabe wird somit weit hinter „Z” mit dem ASCII-Code 91 eingeordnet. Auch der Kleinbuchstabe „a” gilt als „größer” als der Großbuchstabe „Z”.
💡 Selbstverständlich kann sich sort auch nach deutschen Gepflogenheiten richten. Setzen Sie dazu eine der Umgebungsvariablen LANG, LC_ALL oder LC_COLLATE auf einen Wert wie „de”, „de_DE” oder „de_DE.UTF-8” (der genaue Wert hängt von Ihrer Distribution und Systemumgebung ab). Wenn Sie diese Einstellung nur für das sort-Kommando haben wollen, dann ist eine Angabe der Form
$ … | LC_COLLATE=de_DE.UTF-8 sort
möglich. Der Wert von LC_ALL hat Vorrang vor dem Wert von LC_COLLATE, der wiederum Vorrang vor dem Wert von LANG hat. Die deutsche Sortierreihenfolge sorgt übrigens als Nebeneffekt dafür, dass Groß- und Kleinschreibung ignoriert werden.
Wenn Sie nichts anderes angeben, wird „lexikographisch” unter Betrachtung der kompletten Zeile sortiert. Das heißt, wenn die ersten Zeichen zweier Zeilen gleich sind, entscheidet das erste verschiedene Zeichen weiter hinten in der Zeile über deren relative Anordnung. Natürlich kann sort nicht nur nach der ganzen Zeile, sondern auch „gezielt” nach den „Spalten” oder Feldern einer Tabelle sortieren. Die Felder werden beginnend mit 1 nummeriert. Mit der Option „-k 2” wird das erste Feld ignoriert und das zweite Feld jeder Zeile zum Sortieren herangezogen. Sind die Werte zweier Zeilen im zweiten Feld gleich, wird der Rest der Zeile betrachtet, sofern Sie nicht mit Optionen wie »-k 2,3« das letzte anzuschauende Feld angeben. Mit der Option „-k 2,2” wird nur nach dem Wert der zweiten Spalte sortiert. Es ist übrigens auch erlaubt, im selben Kommando mehrere -k-Optionen anzugeben.
💡 Sort unterstützt außerdem eine veraltete Form der Positionsangabe: Hier werden die Felder beginnend mit 0 nummeriert und das Startfeld wird mit „+𝑚” und das Stoppfeld mit „-𝑛” angegeben. Um die Unterschiede zur modernen Form komplett zu machen, ist die Angabe des Stoppfelds auch noch „exklusiv” – benannt wird das erste Feld, nach dem nicht mehr sortiert werden soll. Die Beispiele von oben wären also »+1«, »+1 -3« und »+1 -2«.
Als Trennmarkierung zwischen den verschiedenen Feldern dient das Leerzeichen. Folgen mehrere Leerzeichen aufeinander, wird nur das erste als Trennzeichen interpretiert; die restlichen werden dem Inhalt des folgenden Feldes zugeordnet. Ein kleines Beispiel ist die Meldeliste für den alljährlichen Marathonlauf des TSV Lahmhausen. Zunächst stellen wir sicher, dass die Standardsprachumgebung des Systems („POSIX”) verwendet wird, indem wir die entsprechenden Umgebungsvariablen zurücksetzen. (Die vierte Spalte enthält übrigens die Startnummer.)
$ unset LANG LC_ALL LC_COLLATE
$ cat teilnehmer.dat
Schulz Hugo SV Schnaufenberg 123 Herren Schleicher Detlef TSV Lahmhausen 13 Herren Flöttmann Fritz Sportfreunde Renntal 217 Herren Springinsfeld Karlheinz TV Jahnstein 154 Herren von Traben Gesine TV Jahnstein 26 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen Schwitz Sieglinde Sportfreunde Renntal 93 Damen Rasbichel Katja TSV Lahmhausen 119 Damen Langbein Leni SV Schnaufenberg 55 Damen Zielinger Hannes TV Jahnstein 45 Herren Fluschinsky Käthe Sportfreunde Renntal 57 Damen
Versuchen wir zunächst, eine Liste alphabetisch nach dem Nachnamen zu sortieren. Das ist prinzipiell einfach, da die Nachnamen ganz vorne in der Zeile stehen:
$ sort teilnehmer.dat
Fluschinsky Käthe Sportfreunde Renntal 57 Damen Flöttmann Fritz Sportfreunde Renntal 217 Herren Langbein Leni SV Schnaufenberg 55 Damen Rasbichel Katja TSV Lahmhausen 119 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen Schleicher Detlef TSV Lahmhausen 13 Herren Schulz Hugo SV Schnaufenberg 123 Herren Schwitz Sieglinde Sportfreunde Renntal 93 Damen Springinsfeld Karlheinz TV Jahnstein 154 Herren Zielinger Hannes TV Jahnstein 45 Herren von Traben Gesine TV Jahnstein 26 Damen
Sie sehen sicherlich die beiden kleinen Probleme in dieser Liste: Einerseits sollte „Flöttmann” vor „Fluschinsky” und andererseits „von Traben” vor „Zielinger” einsortiert werden. Beide Fehler verschwinden, wenn wir darauf achten, die deutschen Sortierregeln einzuhalten.
$ LC_COLLATE=de_DE sort teilnehmer.dat
Flöttmann Fritz Sportfreunde Renntal 217 Herren Fluschinsky Käthe Sportfreunde Renntal 57 Damen Langbein Leni SV Schnaufenberg 55 Damen Rasbichel Katja TSV Lahmhausen 119 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen Schleicher Detlef TSV Lahmhausen 13 Herren Schulz Hugo SV Schnaufenberg 123 Herren Schwitz Sieglinde Sportfreunde Renntal 93 Damen Springinsfeld Karlheinz TV Jahnstein 154 Herren von Traben Gesine TV Jahnstein 26 Damen Zielinger Hannes TV Jahnstein 45 Herren
Als Nächstes sortieren wir nach dem Vornamen:
$ sort -k 2,2 teilnehmer.dat
Schulz Hugo SV Schnaufenberg 123 Herren Schwitz Sieglinde Sportfreunde Renntal 93 Damen Langbein Leni SV Schnaufenberg 55 Damen Flöttmann Fritz Sportfreunde Renntal 217 Herren Zielinger Hannes TV Jahnstein 45 Herren Rasbichel Katja TSV Lahmhausen 119 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen Schleicher Detlef TSV Lahmhausen 13 Herren Fluschinsky Käthe Sportfreunde Renntal 57 Damen Springinsfeld Karlheinz TV Jahnstein 154 Herren von Traben Gesine TV Jahnstein 26 Damen
Hier kommt die oben erwähnte Eigenschaft von sort zum Tragen, das erste einer Folge von Leerzeichen als Trenner zu interpretieren und die folgenden dem Anfang des nächsten Feldes zuzuschlagen. Wie Sie sehen, sind die Vornamen zwar alphabetisch sortiert, jedoch immer nur innerhalb der jeweils gleich langen Nachnamen. Dies können Sie durch die Option -b beheben. Dabei werden Folgen von Leerzeichen wie ein einziges behandelt:
$ sort -b -k 2,2 teilnehmer.dat
Schleicher Detlef TSV Lahmhausen 13 Herren Flöttmann Fritz Sportfreunde Renntal 217 Herren Zielinger Hannes TV Jahnstein 45 Herren Schulz Hugo SV Schnaufenberg 123 Herren Springinsfeld Karlheinz TV Jahnstein 154 Herren Rasbichel Katja TSV Lahmhausen 119 Damen Fluschinsky Käthe Sportfreunde Renntal 57 Damen Langbein Leni SV Schnaufenberg 55 Damen Schwitz Sieglinde Sportfreunde Renntal 93 Damen von Traben Gesine TV Jahnstein 26 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen
Die korrekte Sortierung von „Karlheinz”, „Katja” und „Käthe” erreichen Sie durch die Verwendung der deutschen Sprachumgebung. Dabei werden Sie feststellen, dass diese auch die -b-Option impliziert. Die sortierte Liste enthält jedoch noch einen Schönheitsfehler, siehe hierzu Übung 8.1.4.
Sie können das zu sortierende Feld noch genauer bestimmen, wie das folgende Beispiel zeigt:
$ sort -br -k 2.2 teilnehmer.dat
Fluschinsky Käthe Sportfreunde Renntal 57 Damen Schulz Hugo SV Schnaufenberg 123 Herren Flöttmann Fritz Sportfreunde Renntal 217 Herren von Traben Gesine TV Jahnstein 26 Damen Rasbichel Ulla TSV Lahmhausen 117 Damen Schwitz Sieglinde Sportfreunde Renntal 93 Damen Schleicher Detlef TSV Lahmhausen 13 Herren Langbein Leni SV Schnaufenberg 55 Damen Rasbichel Katja TSV Lahmhausen 119 Damen Springinsfeld Karlheinz TV Jahnstein 154 Herren Zielinger Hannes TV Jahnstein 45 Herren
Tabelle 8.3: Optionen für sort (Auswahl)
| Optionen | Wirkung |
|---|---|
| -b (blank) | ignoriert führende Leerzeichen im Feldinhalt |
| -d (dictionary) | sortiert nach Wörterbuch-Kriterien, d. h. nur Buchstaben, Ziffern und Leerzeichen werden berücksichtigt |
| -f (fold) | kine Unterscheidung von Groß und Kleinbuchstaben |
| -i (ignore) | nicht druckbare Zeichen werden ignoriert |
| -k ⟨Feld⟩[,⟨Fed’⟩] (key) | Sortiere gemäß ⟨Feld⟩ (bis einschließlich ⟨Feld’⟩) |
| -n (numeric) | betrachtet Feldinhalt als Zahl und sortiert nach dem numerischen Wert, führende Leerzeichen werden ignoriert |
| -o datei (output) | "schreibt Arbeitsergebnis in eine Datei, deren Name hier mit der Ursprungsdatei übereinstimmen darf! |
| -r (reverse) | "sortiert absteigend, also von Z nach A" |
| -t⟨Zeichen⟩ (terminate) | das ⟨Zeichen⟩ dient als Feldtrennzeichen |
| -u (unique) | " gibt nur die erste einer Folge von identischen Zeilen aus" |
Hier wird die Datei „teilnehmer.dat” absteigend nach dem zweiten Zeichen der zweiten Tabellenspalte sortiert, also dem zweiten Buchstaben des Vornamens (sehr sinnvoll!). Auch in diesem Fall ist es erforderlich, führende Leerzeichen mit der Option -b zu ignorieren. (Der Schönheitsfehler aus Übung 8.1.4 manifestiert sich auch hier.)
Mit der Option -t (engl. terminate, „begrenzen”) können Sie statt des Leerzeichens beliebige andere Trennzeichen festlegen. Dies ist grundsätzlich eine gute Idee, da die zu sortierenden Felder dann Leerzeichen enthalten dürfen. Hier ist eine Fassung unserer Beispieldatei, die sich bequemer verwenden lässt (wenn auch schwerer zu lesen ist):
Schulz:Hugo:SV Schnaufenberg:123:Herren Schleicher:Detlef:TSV Lahmhausen:13:Herren Flöttmann:Fritz:Sportfreunde Renntal:217:Herren Springinsfeld:Karlheinz:TV Jahnstein:154:Herren von Traben:Gesine:TV Jahnstein:26:Damen Rasbichel:Ulla:TSV Lahmhausen:117:Damen Schwitz:Sieglinde:Sportfreunde Renntal:93:Damen Rasbichel:Katja:TSV Lahmhausen:119:Damen Langbein:Leni:SV Schnaufenberg:55:Damen Zielinger:Hannes:TV Jahnstein:45:Herren Fluschinsky:Käthe:Sportfreunde Renntal:57:Damen
Die Sortierung nach dem Vornamen liefert mit der Option „LC_COLLATE=de_DE sort -t: -k2,2” nun korrekte Ergebnisse. Auch eine Sortierung nach der Startnummer (nun Feld 4, unabhängig von der Anzahl der Leerzeichen im Vereinsnamen) ist nun einfacher:
$ sort -t: -k4 teilnehmer0.dat
Rasbichel:Ulla:TSV Lahmhausen:117:Damen
Rasbichel:Katja:TSV Lahmhausen:119:Damen
Schulz:Hugo:SV Schnaufenberg:123:Herren
Schleicher:Detlef:TSV Lahmhausen:13:Herren
Springinsfeld:Karlheinz:TV Jahnstein:154:Herren
Flöttmann:Fritz:Sportfreunde Renntal:217:Herren
von Traben:Gesine:TV Jahnstein:26:Damen
Zielinger:Hannes:TV Jahnstein:45:Herren
Langbein:Leni:SV Schnaufenberg:55:Damen
Fluschinsky:Käthe:Sportfreunde Renntal:57:Damen
Schwitz:Sieglinde:Sportfreunde Renntal:93:Damen
Standardmäßig erfolgt die Sortierung nach der Startnummer lexikographisch: „117” und „123” stehen vor „13” und dieses wiederum vor „154”. Dies lässt sich ändern, indem Sie die Option -n angeben und somit einen numerischen Vergleich erzwingen:
$ sort -t: -k4 -n teilnehmer0.dat Schleicher:Detlef:TSV Lahmhausen:13:Herren von Traben:Gesine:TV Jahnstein:26:Damen Zielinger:Hannes:TV Jahnstein:45:Herren Langbein:Leni:SV Schnaufenberg:55:Damen
Fluschinsky:Käthe:Sportfreunde Renntal:57:Damen Schwitz:Sieglinde:Sportfreunde Renntal:93:Damen Rasbichel:Ulla:TSV Lahmhausen:117:Damen Rasbichel:Katja:TSV Lahmhausen:119:Damen Schulz:Hugo:SV Schnaufenberg:123:Herren Springinsfeld:Karlheinz:TV Jahnstein:154:Herren Flöttmann:Fritz:Sportfreunde Renntal:217:Herren
Die wichtigsten Optionen für sort finden Sie in Tabelle 8.3. Es empfiehlt sich in jedem Fall, die Dokumentation des Programms genau zu studieren, denn sort ist ein vielseitiges und leistungsfähiges Programm, mit dem Sie sich jede Menge Arbeit sparen können.
Das Kommando uniq hat die wichtige Funktion, von unmittelbar aufeinanderfolgenden „gleichen” Zeilen in der Eingabe nur eine durchzulassen. Wann zwei Zeilen als „gleich” gelten, lässt sich – wie üblich – durch Optionen einstellen. uniq unterscheidet sich von den meisten bisher gesehenen Programmen dadurch, dass es höchstens eine benannte Eingabedatei akzeptiert; ein zweiter Dateiname wird als Name für die Ausgabedatei angesehen (ersatzweise die Standardausgabe). Wird keine Datei im uniq-Aufruf benannt, liest uniq, wie vorgesehen, seine Standard-Eingabe.
Uniq funktioniert am besten, wenn die Eingabezeilen sortiert sind, sodass alle gleichen Zeilen hintereinander stehen. Ist das nicht der Fall, ist nicht garantiert, dass jede Zeile in der Ausgabe nur einmal vorkommt.
$ cat uniq-test
Hipp Hopp Hopp Hipp Hipp Hopp
$ uniq uniq-test
Hipp
Hopp Hipp Hopp
Vergleichen Sie das mit der Ausgabe von sort -u:
$ sort -u uniq-test
Hipp Hopp
Übungen
✏️ 8.12 [!2] Sortieren Sie die Teilnehmerliste in der Datei „teilnehmer0.dat” (mit Doppelpunkten als Feldtrenner) zunächst nach den Vereinsnamen und innerhalb der Vereine anschließend nach den Nach- und Vornamen der Spieler (in dieser Reihenfolge).
✏️ 8.13 [3] Wie können Sie die Teilnehmerliste aufsteigend nach Vereinsnamen und innerhalb der Vereine absteigend nach Startnummern sortieren? (Tipp: Lesen Sie die Dokumentation!)
✏️ 8.14 [!2] Was ist der „Schönheitsfehler“, von dem in den Beispielen die Rede ist, und warum tritt er auf?
✏️ 8.15 [2] In einem Verzeichnis befinden sich Dateien mit den folgenden Namen:
01-2002.txt 01-2003.txt 02-2002.txt 02-2003.txt 03-2002.txt
✁✁✁✁✁" 03-2003.txt 04-2002.txt 04-2003.txt
11-2002.txt 11-2003.txt 12-2002.txt 12-2003.txt
Geben Sie ein Sortierkommando ein, mit dem Sie die Ausgabe von „ls” in die „chronologisch richtige” Reihenfolge:
01-2002.txt
02-2002.txt
✁✁✁✁✁
12-2002.txt
01-2003.txt
✁✁✁✁✁
12-2003.txt
bringen können.
8.4.2 Spalten und Felder – cut, paste & Co
Während Sie mit dem Kommando „grep” Zeilen einer Textdatei durchsuchen und ausschneiden können, arbeitet sich „cut” (engl. für „schneiden”) gewissermaßen vertikal durch einen Text und schneidet Spalten aus. Dies kann auf zwei Arten erfolgen:
Eine Möglichkeit ist die absolute Bearbeitung von Spalten. Diese Spalten entsprechen einzelnen Zeichen einer Zeile. Um solche Spalten auszuschneiden, muss nach der Option -c (engl. „column”, „Spalte”) die Spaltennummer angegeben werden. Sollen mehrere Spalten in einem Schritt ausgeschnitten werden, können diese als kommaseparierte Liste festgelegt werden. Auch die Angabe von Spaltenbereichen ist zulässig.
$ cut -c 15,1-5 teilnehmer.dat
SchulH SchleD
FlöttF SprinK von TG
✁✁✁✁✁
Im Beispiel werden der Anfangsbuchstabe des Vornamens sowie die ersten fünf Zeichen des Nachnamens ausgeschnitten. Dies veranschaulicht auch die bemerkenswerte Tatsache, dass die Ausgabe immer in der Reihenfolge erfolgt, in der die ausgeschnittenen Spalten in der Eingabe stehen. Selbst wenn sich die ausgewählten Spaltenbereiche überlappen, wird jedes Zeichen der Eingabe höchstens einmal ausgegeben:
$ cut -c 1-5,2-6,3-7 teilnehmer.dat
Schulz Schleic Flöttma Springi von Tra
✁✁✁✁✁
Die zweite Möglichkeit ist das Ausschneiden relativ in Feldern. Diese werden durch Trennzeichen voneinander abgegrenzt. Wenn Sie feldweise ausschneiden möchten, benötigt Cut die Option -f (engl. field, „Feld”) und die gewünschte Feldnummer. Für diese gelten die gleichen Regeln wie für die Spaltennummern. Übrigens schließen sich die Optionen -c und -f gegenseitig aus.
Als Trenner ist das Tabulatorzeichen voreingestellt. Andere Trenner lassen sich mit der Option -d (engl. „delimiter”, „Trennzeichen”) vorgeben:
$ cut -d: -f 1,4 teilnehmer0.dat
Schulz:123 Schleicher:13 Flöttmann:217 Springinsfeld:154 von Traben:26 Rasbichel:117
✁✁✁✁✁
Auf diese Weise werden der Meldeliste die Nachnamen der Teilnehmer (Spalte 1) sowie die Benutzernummern (Spalte 4) entnommen. Als Trennzeichen wird ein Doppelpunkt verwendet. Aus Gründen der Übersichtlichkeit ist hier nur eine verkürzte Ausgabe abgebildet.
💡 Sie können übrigens mit der Option „--output-delimiter” ein anderes Trennzeichen für die Ausgabe festlegen als das, welches für die Eingabe verwendet wird:
$ cut -d: --output-delimiter=': ' -f 1,4 teilnehmer0.dat
Schulz: 123
Schleicher: 13
Flöttmann: 217
Springinsfeld: 154
von Traben: 26
Rasbichel: 117
✁✁✁✁✁
💡 Wenn Sie Spalten oder Felder tatsächlich umsortieren wollen, sind schwerere Geschütze wie die Programme awk oder perl angesagt. Notfalls geht es auch mit dem gleich vorgestellten Kommando „paste”, das ist aber etwas mühselig.
Bei der feldweisen Bearbeitung von Textdateien ist die Option -s (engl. separator, „Trenner”) sinnvoll. Findet „cut -f” Zeilen, die kein Trennzeichen enthalten, werden diese üblicherweise komplett ausgegeben; „-s” verhindert diese Ausgabe.
Das Kommando „paste” (engl. für „zusammenkleben”) fügt die angegebenen Dateien zeilenweise zusammen und wird daher oft in Verbindung mit „cut” benutzt. Wie Sie sicher bemerkt haben, ist „paste” eigentlich kein Filterkommando. Wenn Sie jedoch für einen der Dateinamen ein Minuszeichen angeben, registriert Paste, dass dieser Text aus der Standard-Eingabe gelesen werden soll. Die Ausgabe erfolgt stets auf der Standardausgabe.
Wie erwähnt arbeitet Paste zeilenweise. Werden zwei Dateien parallel durchlaufen, so wird die erste Zeile der ersten Datei und die erste Zeile der zweiten Datei, getrennt durch ein Tabulatorzeichen, zur ersten Zeile der Ausgabe verbunden. Entsprechend wird mit allen weiteren Zeilen verfahren. Wenn Sie statt des Tabulatorzeichens ein anderes Trennzeichen verwenden möchten, können Sie dies mit der Option „-d” festlegen.
Wir können beispielsweise eine Version der Marathon-Meldeliste herstellen, bei der die Startnummer vorne steht:
$ cut -d: -f4 teilnehmer0.dat >startnr.dat
$ cut -d: -f1-3,5 teilnehmer0.dat \
> | paste -d: startnr.dat >tn-startnr.dat
$ cat tn-startnr.dat
123:Schulz:Hugo:SV Schnaufenberg:Herren 13:Schleicher:Detlef:TSV Lahmhausen:Herren 217:Flöttmann:Fritz:Sportfreunde Renntal:Herren 154:Springinsfeld:Karlheinz:TV Jahnstein:Herren 26:von Traben:Gesine:TV Jahnstein:Damen 117:Rasbichel:Ulla:TSV Lahmhausen:Damen 93:Schwitz:Sieglinde:Sportfreunde Renntal:Damen 119:Rasbichel:Katja:TSV Lahmhausen:Damen 55:Langbein:Leni:SV Schnaufenberg:Damen 45:Zielinger:Hannes:TV Jahnstein:Herren 57:Fluschinsky:Käthe:Sportfreunde Renntal:Damen
Diese Datei kann jetzt bequem mit sort -n tn-startnr.dat nach dem numerischen Wert der Startnummer sortiert werden.
Mit der Option -s (engl. serial, „nacheinander”) werden die angegebenen Dateien nacheinander durchlaufen. Zunächst werden alle Zeilen der ersten Datei mit Trennzeichen zu einer Zeile zusammengefasst, anschließend alle Zeilen der zweiten Datei in der zweiten Zeile usw.
$ cat liste1
Hund Katze Maus
$ cat liste2
Ei Blut Kakao
$ paste -s liste*
Hund Katze Maus
Ei Blut Kakao
Alle Dateien, deren Name dem Suchmuster liste* entspricht – in diesem Fall lediglich liste1 und liste2 – werden von Paste zusammengesetzt. Durch die Angabe von -s wird erreicht, dass jede Zeile dieser Dateien eine Spalte der Ausgabe ergibt.
Übungen
✏️ 8.16 [!2] Erstellen Sie eine neue Version der Datei „teilnehmer.dat” mit fester Spaltenbreite, in der die Startnummer und die Vereinszugehörigkeit nicht enthalten sind.
✏️ 8.17 [!2] Erstellen Sie eine neue Version der Datei „teilnehmer0.dat” (mit den durch Doppelpunkt getrennten Feldern), in der weder die Startnummer noch die Vereinszugehörigkeit aufgeführt sind.
✏️ 8.18 [3] Erzeugen Sie eine Version der Datei „teilnehmer0.dat”, bei der die Felder nicht durch Doppelpunkte, sondern durch die Zeichenkette „»,␣»” (Komma, gefolgt von einem Leerzeichen) getrennt sind.
✏️ 8.19 [3] Wie viele verschiedene Gruppen werden von Benutzern auf Ihrem System als primäre Gruppen verwendet? (Die primäre Gruppe eines Benutzers ist im vierten Feld der Datei /etc/passwd zu finden.)
8.5 Kommandos in diesem Kapitel
| Kommando | Beschreibung | manpage |
|---|---|---|
| cat | Hängt Dateien aneinander | cat(1) |
| cut | Extrahiert Felder oder Spalten aus seiner Eingabe | cut(1) |
| head | Zeigt den Anfang einer Datei an | head(1) |
| paste | Fügt verschiedene Eingabedateien zeilenweise aneinander | paste(1) |
| reset | Setzt den Bildschirmzeichensatz auf einen ”vernünftigen“ Wert | tset(1) |
| sort | Sortiert die Zeilen seiner Eingabe | sort(1) |
| tail | Zeigt das Ende einer Datei an | tail(1) |
| tee | Kopiert die Standardeingabe in die Standardausgabe und außerdem in Dateien | tee(1) |
| uniq | Ersetzt Folgen von gleichen Zeilen in der Eingabe durch die erste solche | uniq(1) |
8.6 Zusammenfassung
-
Jedes Linux-Programm unterstützt die Standard-Ein- und -Ausgabe-Kanäle stdin, stdout und stderr.
-
Die Standardausgabe und die Standardfehlerausgabe können mit den Operatoren > und >>, die Standardeingabe mit dem Operator < umgeleitet werden.
-
Über Pipelines lassen sich die Standardaus- und -eingabe von Programmen direkt (ohne Zwischendateien) miteinander verbinden.
-
Mit dem Kommando „tee” können Zwischenergebnisse einer Pipeline in Dateien gespeichert werden.
-
Filterkommandos (auch „Filter” genannt) lesen ihre Standardeingabe, manipulieren sie und schreiben die Ergebnisse auf die Standardausgabe.
-
sort ist ein vielseitiges Sortierprogramm.
-
Das Kommando cut schneidet bestimmte Spaltenbereiche oder Felder jeder Zeile der Eingabe aus.
-
Mit dem Kommando „paste” können die Zeilen von Dateien aneinandergehängt werden.
-
Bekanntlich geht der ASCII nur bis 127. Wirklich gemeint ist hier der ASCII zusammen mit der gerade aktuellen Erweiterung für die Zeichen mit den Codes ab 128, also zum Beispiel ISO-8859-1, auch bekannt als ISO-Latin-1. ↩