Die meisten Daten liegen als Textdatei vor, meistens mit mehr oder weniger gut benannten Spalten von Zahlen. Um die zu verarbeiten und darzustellen, schreibe ich mir meistens Skripte, ganz früher in C++, dann in Perl, heute in Python. Manchmal nehme ich auch gnuplot dazu, das ist eigentlich schon alles was man braucht. Ganz oft muss man aber nur Daten umformen oder zusammenkopieren, und da bietet Linux auf der Kommandozeile reichlich Werkzeuge, kleine mächtige Programme die man erstaunlich schlau zusammensetzen kann. Muss man aber erstmal kennen, und ich habe im Laufe der Zeit erst begonnen die kennen zu lernen. Meistens gibt es ja auch einen anderen Weg (im schlimmsten Fall Excel/OpenCalc *grusel*). Aber seit ich versuche, aktiv nach einer einfachen Lösung zu suchen wenn mir ein eigentlich einfaches Problem begegnet, stelle ich fest dass es die meisten Lösungen schon gibt. Daher will ich mal ein paar Tricks auf der Linux-Konsole vorstellen. Übrigens rate ich euch (wobei die wenigsten Leute so dokumentierfaul sind wie ich) für alles, was ihr öfters braucht doch ein Skript zu schreiben. Man kann ja auch die Befehle in ein Shellskript packen. Denn sonst habt ihr nach 2 Tagen die Kommandos vergessen (bzw aus der history verloren). Ich gehe mal davon aus, dass ihr ganz grob Linux und die Shell kennt (ich benutze ‘konsole’ vom KDE, auch in Gnome) und die häufigsten Befehle, also ls, cp, mkdir etc. beherrscht und auch wisst, dass ihr mit man xxx die Hilfe zu einem Befhl ansehen könnt, wo z.B. die ganzen Parameter erklärt werden. Es gibt sicher noch deutlich mehr Tools als ich hier erwähne, die kenne ich dann u.U. halt auch noch nicht. Daher freue ich mich auch, wenn ihr eure Lieblingstricks verratet.
Kleine Kniffe
Zunächst ein paar kleine Tricks um schneller Befehle ausführen zu können:
- Wahrscheinlich bekannt ist, dass man mit ↑ und ↓ durch die history der Befhle gehen könnt und alte Befehle nochmal ausführen könnt. Mit TAB kann man begonne Wörter, meistens Dateinamen, ergänzen lassen. Wenn er mehrere Möglichkeiten gibt, gibt Doppel-TAB eine Liste der Möglichkeiten.
- Man kann die history auch durchsuchen. Mit Strg+R und einem Suchbegriff beginnt ihr die Suche rückwärts durch die history (emacs-Style, daher kann man das mit Strg+G auch abbrechen). Mehrmals Strg+R drücken geht schrittweise rückwärts. Mit Enter führt ihr den Befehle aus oder mit Pfeil links, Ende oder etwas ähnlichem wird er auf die Shell geholt und ist editierbar.
- Mit !xx führt ihr sofort den letzten Befehl aus, der mit ‘xx’ anfing. Sehr nützlich, aber versucht wenigstens zwei Buchstaben mitzugeben, da ihr sonst manchmal unfreiwillig einen falschen Befehl ausführt.
- Kann man manchmal brauchen: ^2^3 führt den letzten Befehl aus, ersetzt aber die erste Zahl (2) durch die zweite(3), aber nur beim ersten Auftreten.
Rohrleitungen
Die meisten Befehle entfalten nur dann ihre Macht, wenn man weiß wie man sie verknüpft. Normalerweise gibt z.B. cat daten.txt den Inhalt der Datei ‘daten.txt’ auf die Konsole aus, was selten nützlich ist. Aber die Shell ist in der Lage, die Ausgabe umzuleiten – z.B. als Eingabe für einen anderen Befehl. Das funktioniert mit der ‘pipe’ |
Die findet ihr, wenn ihr AltGr zusammen mit der <-Taste drückt. Es ist wie Rohrpost: Die Ausgabe des einen Befehls wird als Eingabe an den nächsten geleitet. Das funktioniert bei den meisten Befehlen intuitiv gut und richtig - und wenn nicht ist es mir meistens zu mühsam herauszufinden warum nicht. Manchmal geht da was mit xargs.
Bauen wir also ein paar einfache Leitungen.
Problem: Ihr habt eine Datei die ihr plotten wollt, aber leider sind die Zeilen nicht nummeriert. Abhilfe kann der Befehl nl schaffen, der Zeilennummern zu seiner Eingabe hinzufügt – die man ihm per Rohrpost schickt. Also gebt die Datei mit cat aus und lenkt es zu nl:
cat daten.txt | nl
Das schickt euch das Ergebnis wieder an die Konsole. Sagen wir, ihr wollt erst mal in Ruhe durchsehen, was da rauskommt. Dann könnt ihr es zuerst weiterschicken an less:
cat daten.txt | nl | less
Wenn euch das Ergebnis gefällt, kann man die Ausgabe auch in eine Datei lenken:
cat daten.txt | nl > datenNl.txt
.
Problem: Ihr habt zwei Hilfsdateien mit je zwei Spalten Daten, möchtet aber eigentlich lieber alle vier Spalten nebeneinander haben.
Da hilft paste:
paste datei1 datei2 > daten.txt
setzt die Spalten nebeneinander. Sagen wir aber mal, die erste Spalte ist gleich in beiden Dateien. Dann versucht lieber ein join:
join datei1 datei2 > daten.txt
und die erste Spalte wird nur einmal erscheinen.
Problem: Die ersten oder letzten Zeilen sollen nicht erscheinen.
Dazu nehmt ihr head und tail. Einfach als head daten.txt seht ihr die ersten paar Zeilen einer Datei (oder die letzten mit tail). Sagen wir mal, ihr wollt die erste Zeile abschneiden. Dann schaut erst nach, wieviele Zeilen die Datei hat:
wc -l < daten.txt
Und dann setzt ihr diese Zahl (minus 1) in den tail ein, dem ihr die Zeilenzahl die vom Ende genommen werden soll mit -n mitteilen könnt:
tail -n nnn daten.txt
Nützlich ist auch tail -f daten.txt, das die Änderungen an einer Datei überwacht und immer schreibt, was am Ende dazukommt. Nützlich z.B., wenn eine Simulation läuft, die ihr mit nohup von der Sitzung abgekoppelt habt und verfolgen wollt, was in nohup.out passiert.
Finden und Graben
Sehr häufig braucht man grep. Damit könnt ihr quasi einen Suchbegriff angeben und nur Zeilen mit diesem Begriff ausgeben. Das funktioniert mit Dateien:
grep lala daten.txt
Das funktioniert auch für alle Datein, mit -r auch rekursiv durch Unterverzeichnisse:
grep -r lala *.txt
Aber ihr könnt damit auch über die Pipe andere Ausgaben filtern. Beispielsweise findet find alle Dateien im Verzeichnis und Unterordnern, und da kann man einzelne Namen rausfiltern:
find . | grep dat
Weitere nützliche Parameter für grep sind -A n und -B n, mit denen sich n Zeilen vor und nach der Zeile mit dem Suchbegriff dazu ausgeben lassen und -i um Groß-/Kleinschreibung zu ignorieren. grep hat jede Menge Optionen, schaut in die manpage. Man kann es vor allem auch mit Regular Expressions füttern.
sed und awk
Und schließlich noch zwei mächtige Werkzeuge, die schon kleine eigene Sprachen sind, bei denen ich sed aber nur anreißen will. sed kann Strings in Dateien oder Ausgaben filtern und ersetzen. Es kann noch viel mehr, aber ich benutze es bislang nur um beispielsweise Wörter zu ersetzen. Dazu gibt man auch eine Regular Expression an:
sed s/m/cm/ daten.txt > daten_neu.txt
ersetzt in der Datei daten.txt alle 'm' durch 'cm'.
awk kann direkt die Zahlen in Spalten verarbeiten und ist eine Mini-Programmiersprache. Kompliziertere Programme lassen sich auch als Skript speichern, aber sehr oft kann man es einsetzen, um Datensätze umzuformen und schnelle Berechnungen anzustellen. Die Befehle muss man dabei in '{...}' setzen.
Sagen wir mal, daten.txt enthält drei Spalten mit Zahlen, aber wir wollen nur die zweite ausgeben, dafür aber Zeilennummern hinzufügen:
cat daten.txt | awk '{print NR " " $2}'
NR ist die aktuelle Zeilennummer, $1,$2... ist die Zahl in der ersten, zweiten,... Spalte und mit " " muss man den Zeilenabstand von Hand einfügen. Natürlich könnte man die Zeilennummer auch so einfügen:
cat daten.txt | awk '{print $2}' | nl
Man könnte aber auch die Spalten voneinander abziehen:
cat daten.txt | awk '{print $2-$1}'
Jetzt wollen wir die ganze Zeile ausgeben, falls die Zahl in Spalte 2 größer als 5 ist. Die ganze Zeile bekommt man mit $0:
cat daten.txt | awk '{if($2>5){print $0}}'
Außerdem kann man mit BEGIN und END Blöcke einfügen, die vor bzw. nach der Bearbeitung der Eingabe ausgeführt werden. So ein RMS berechnen, also das Quadrat der Differenz zweier Zahlen, aufaddiert über alle Zeilen, dann geteilt durch die Zeilenzahl und die Wurzel draus:
cat d.txt |awk 'BEGIN{rms=0}{rms+=($2-$1)**2}END{print sqrt(rms/NR)}'
Voila, das waren erstmal genug Tricks für einen Beitrag!
Kommentare (26)