Kommandozeile Schnellstart – Pipe shell command

Übersicht:

Willkommen zur Lektion zum Thema Pipes unter Linux. Pipes sind eine Methode, wie zwei Prozesse untereinander Daten austauschen können. Man kann sich das so vorstellen, dass die Daten, die am Ende eines Prozesses entstehen durch ein Rohr (englisch: Pipe) zu einem anderen Prozess geleitet werden, welcher diese Daten dann verarbeitet. Somit lassen sich sehr effektiv Ketten von Prozessen bzw. Programmen bilden, durch die die Daten dann laufen. Der große Vorteil dieser Methode besteht darin, dass die einzelnen Programme sehr klein sind und nur spezifische Aufgaben übernehmen. Somit sind die Teile der Kette immer genau für den Zweck entworfen, den sie später auch erfüllen.

Anwendung und Syntax:

Der Pipeoperator wird durch einen senkrechten Strich repräsentiert. Die allgemeine Syntax lautet:

 <Programm1> | <Programm2>

Hierbei wird der Output von Programm 1 als Input von Programm 2 verwendet. Hierzu ein Beispiel:

echo "Hello World" | cut -d " " -f1

Wir wollen uns genauer ansehen, was hier passiert.

 echo "Hello World"

Das Programm echo gibt einfach eine Zeichenkette aus, in diesem Fall "Hello World".

 cut -d " " -f1

Das Programm cut schneidet eine Zeichenkette anhand eines Delimiters (Parameter d) und selektiert dann, welchen Teil der Zeichenkette es ausgibt (Parameter f).

Wie wir gelernt haben, wird bei einer Pipe der Output des ersten Programms, in dem fall echo als Input des zweiten Programmes, in dem Fall cut verwendet. Es ergibt sich folgender Ablauf:

  • echo gibt die Zeichenkette "Hello World" aus
  • die Zeichenkette "Hello World" wird an cut übergeben und dient als Input
  • cut sucht anhand des Parameters d alle Vorkommen des Delimiters (in dem Fall " ", als das Leerzeichen) und findet es zwischen "Hello" und "World")
  • cut teilt die Zeichenkette in "Hello" und "World" auf und selektiert anhand des Parameters f den ersten Teil der Zeichenkette vor dem Delimiter.
  • cut gibt das Ergebnis seiner Operation als Standardoutput aus.

Der Output ist in dem Fall also "Hallo".

Ein weiteres Beispiel:

Nehmen wir an, wir wollen alle IP-Adressen, die in der Datei /etc/hosts definiert sind, auflisten und in einer Datei speichern. Die Datei /etc/hosts enthält aber neben IP-Addressen auch die hostnamen, die wir in dem Fall nicht brauchen.

Hinweis: Die Datei /etc/hosts sieht oft bei verschiedenen Nutzern etwas anders aus. Um das Beispiel nachvollziehen zu können, liste ich an der Stelle meine /etc/hosts-Datei auf.

127.0.0.1 localhost
127.0.1.1 Precision-7520
10.22.10.201 build

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback cat /etc/hosts | cut -d " " -f1 | cut -d$'t' -f1| grep . |grep -v '^#'
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Als erstes suchen wir nach einem Werkzeug, um die Datei /etc/hosts an den stdout auszugeben. Das Mittel der Wahl ist in dem Fall das Programm cat. Der erste Teil unserer Befehlskette lautet also

 cat /etc/hosts

Wir sehen, dass die IP-Adressen in der ersten Spalte stehen, und dass sie vom Rest der Zeile durch ein Leerzeichen getrennt sind. Wir können also wieder den Befehl cut benutzen. Der richtige Befehl lautet also wieder wie oben:

 cut -d " " -f1

Wie oben, verbinden wir beide Befehle durch eine Pipe.

 cat /etc/hosts | cut -d " " -f1

 

Wir stellen fest, dass dies dem Ergebnis, das wir haben wollen, schon sehr nahe kommt. Immer wieder kommt es aber vor, dass IP-Adresse und Hostname in der Datei /etc/hosts nicht durch ein Leerzeichen, sondern durch ein Tabulatorsteuerzeichen getrennt sind. Um diesen Fall abzudecken, wenden wir den Befehl cut einfach ein weiteres Mal an.

 cat /etc/hosts | cut -d " " -f1 | cut -d$'t' -f1

Wir stellen nun weiterhin fest, dass die Datei /etc/hosts einige Leerzeilen enthält. Wir nutzen den Befehl grep um uns nur die Zeilen ausgeben zu lassen, die keine Leerzeilen enthalten. Damit wächst unsere Befehlskette um ein weiteres Glied:

 cat /etc/hosts | cut -d " " -f1 | cut -d$'t' -f1| grep .

Nun stellen wir fest, dass wir in einer einer Zeile noch eine Raute stehen haben, die bisher durch keinen unserer Befehle entfernt wurde. Wir nutzen erneut den Befehl grep, um alle Zeilen zu selektieren, die keine Raute enthalten.

 cat /etc/hosts | cut -d " " -f1 | cut -d$'t' -f1| grep . |grep -v '^#'

Jetzt erhalten wir folgenden Output:

127.0.0.1
127.0.1.1
10.22.10.201
::1
fe00::0
ff00::0
ff02::1
ff02::2

Um diesen Output jetzt in eine Datei zu speichern, müssen wir lediglich den stdout-Stream in eine Datei umleiten:

 cat /etc/hosts | cut -d " " -f1 | cut -d$'t' -f1| grep . |grep -v '^#' > output.txt

Wir haben nun eine Liste aller IP-Adressen erhalten, die in der Datei /etc/hosts stehen. Diese Liste könnten wir z.B. an einen ping-Befehl übergeben, der alle IP-Adressen der Reihe nach durchgeht und prüft, ob sie erreichbar sind.

Hinweis: Wer sich mit den Tools auf der Kommandozeile gut auskennt, erkennt, dass man statt cat und cut auch awk und statt grep auch sed hätte nutzen können. Wie so oft führen auch unter Linux mehrere Wege ans Ziel.

 

Übungen:

    1. Sammle alle Telefonnummern aus der Datei addresses.txt und speichere sie in der Datei output.txt
       cat addresses.txt | cut -d " " -f2

Zusammenfassung:

Wie man sieht, sind Pipes ein sehr mächtiges Werkzeug um Befehlsketten zu bilden. Pipes kombinieren elementare Linuxprogramme um komplexe Aufgaben auszuführen. Sie sind ein unverzichtbares Werkzeug zum Arbeiten auf der Kommandozeile.