Bei Linux am Dienstag hatten wir diesmal zwar keine größeren Vorträge zu Linuxprogrammen, aber dennoch etwas neues für die meisten Shellfanatiker: paste .
Zeilen mit Bash zusammenfügen
Nehmen wir mal diese Daten einer beliebigen Datei oder Shellausgabe:
Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
Wir haben also in den ungerade Zeilen 1,3,5… usw. den Text „Username:<TAB>UserX<LF>“ stehen und in den geraden Zeilen „<TAB>2134 MB<LF>“. Diese Zeilen sollen zusammengefügt werden, daß Username und Anzahl der MB in einer Zeile mit 2(3) Spalten steht:
Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
Wie bekommt man das hin?
Da geb es erst einmal einen kleinen Dämpfer, als wir versuchten die <LF> mit sed zu ersetzen, was nicht funktionierte und selbst wenn es funktioniert hätte, nicht die Lösung gewesen wäre, weil dann alles in einer Zeile gestanden hätte: sed -e „s/\n//g“ können wir also vom Plan streichen 🙂
Eine kreative Lösung kam dann von Matthias:
$ cat daten.txt | xargs echo | sed -e "s/MB /MB\n/g" | sed -e "s/ /\t/g" Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
Weil es einfacher war damit umzugehen, standen die Ausgangsdaten in einer Textdatei „daten.txt“.
„xargs echo“ gibt jede Zeile der Datei mit echo einzeln aus. Darauf hin wird sed so ausgeführt, daß der resultierende Textblock „…MB “ zu „…MB<LF>“ wird und alle Leerzeichen zu Tabulatoren <TAB>.
Das ist schon einmal eine Möglichkeit, aber es geht einfacher:
$ cat daten.txt | paste - - Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
Es gab keine Vorgabe, daß alle Leerzeichen verschwinden sollten. Wäre das eine Vorgabe gewesen, hätte man am Ende noch das | sed -e „s/ /\t/g“ dranhängen müssen.
$ cat daten.txt | paste - - | sed -e "s/ /\t/g" Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
oder etwas schlanker:
$ cat daten.txt | paste - - | sed -e "s/\t\t/ /g" -e "s/ /\t/g" Username: User1 0.00 MB Username: User#2 0.07 MB Username: User3 4630.98 MB Username: User#4 209.16 MB Username: User5 583.70 MB Username: User#6 896.46 MB Username: User7 809.58 MB Username: User#8 902.74 MB Username: User9 136.84 MB Username: User#10 9156.09 MB Username: User11 372.55 MB Username: User#12 77.75 MB
Merke: paste aus den CoreUtilities kann zwei oder mehr Zeilen einer Ausgabe zusammenfügen.