BASH echo
Beim Programmieren in der BASH bin ich heute ganz schön ins Schwitzen gekommen. Wenn man mit echo
arbeitet und auch ab und zu mal ein Kommando in einer Sub-Shell ausführt, muss man einiges beachten — sonst guckt man u. U. dumm aus der Wäsche. Um das Verhalten von echo
zu verdeutlichen, habe ich ein Verzeichnis testdir
mit den drei Dateien a
, b
und c
angelegt. Was man da mit echo
alles erleben kann, zeigen folgende Beispiele.
$ STRING="Zeile 1\nZeile2\nStern *" $ echo $STRING Zeile 1\nZeile2\nStern a b c
Die Zeilenumbrüche werden nicht interpretiert, aber dafür wird der *
von der BASH durch die Namen der Dateien in testdir
ersetzt. Das lässt sich verhindern, indem man die Variable in Anführungszeichen packt.
$ echo "$STRING" Zeile 1\nZeile 2\nStern *
Super Sache! Sollen Escape-Sequenzen wie ein Zeilenumbruch (\n
) interpretiert werden, so ruft man echo
einfach mit dem Schalter -e
auf:
$ echo -e $STRING Zeile 1 Zeile 2 Stern a b c
Hoppla! Der *
wurde wieder durch die Dateinamen ersetzt. Also schnell die Variable in "
gepackt und den Aufruf wiederholt:
$ echo -e "$STRING" Zeile 1 Zeile 2 Stern *
Soweit so gut, alles kein Problem. Verrückt kanns werden, wenn man die Ausgabe eines Sub-Shell-Aufrufs ausgibt:
$ echo $(echo $STRING) Zeile 1\nZeile 2\nStern a b c
Das innere echo
expandiert den *
, so dass die Dateinamen zu sehen sind. Das äußere echo
schreibt den String auf die Ausgabe.
$ echo $(echo "$STRING") Zeile 1\nZeile 2\nStern a b c
Die gleiche Ausgabe wie weiter oben, nur diesmal expandiert das äußere echo
den *
. Was tun? Wir packen den Sub-Shell-Aufruf einfach in Anführungszeichen:
$ echo "$(echo "$STRING")" Zeile 1\nZeile 2\nStern *
Mit dem Schalter -e
werden die beiden Zeilenumbrüche interpretiert. Dabei spielt es keine Rolle, ob man das -e
zum inneren, äußeren oder zu beiden echo
-Aufrufen hinzufügt.
$ echo "$(echo -e "$STRING")" Zeile 1 Zeile 2 Stern * $ echo -e "$(echo "$STRING")" Zeile 1 Zeile 2 Stern * $ echo -e "$(echo -e "$STRING")" Zeile 1 Zeile 2 Stern *
Das ganze funktioniert natürlich nur, da Anführungszeichen verwendet werden. Innerhalb dieser wird nichts expandiert und auch die Escape-Sequenzen bleiben erhalten.
Mal sehen was passiert, wenn man das eine oder andere Paar "
weglässt.
$ echo -e $(echo -e "$STRING") Zeile 1 Zeile 2 a b c
Das innere echo
expandiert nichts, interpretiert dafür aber die Zeilenumbrüche. Diese gehen jedoch verloren, da der Sub-Shell-Aufruf nicht in Anführungszeichen gesetzt wurde. Der Schalter -e
des äußeren echo
ist daher überflüssig.
$ echo $(echo -e "$STRING") Zeile 1 Zeile 2 a b c
Ein anderes Beispiel:
$ echo -e "$(echo -e $STRING)" Zeile 1 Zeile 2 a b c
Das innere echo
expandiert den *
und interpretiert die Zeilenumbrüche. Das äußere echo
reicht das Ergebnis nur durch. Auch hier ist der Schalter -e
überflüssig.
$ echo "$(echo -e $STRING)" Zeile 1 Zeile 2 a b c
Viel Spaß bei der Shell-Programmierung!