Wenn Sie diesen Befehl ausführen:
ls
Das Terminal zeigt die Ausgabe von an ls
.
Wenn Sie diesen Befehl ausführen:
echo $(ls)
Die Shell erfasst die Ausgabe von $(ls)
und führt eine Wortteilung durch . Standardmäßig IFS
bedeutet dies, dass alle Folgen von Leerzeichen, einschließlich Zeilenumbrüchen, durch ein einzelnes Leerzeichen ersetzt werden. Deshalb echo $(ls)
erscheint die Ausgabe von in einer Zeile.
Weitere Informationen zur Wortteilung finden Sie in den häufig gestellten Fragen zu Greg .
Unterdrückung der Wortteilung
Die Shell führt keine Wortteilung für Zeichenfolgen in Anführungszeichen durch. So können Sie die Wortteilung unterdrücken und die mehrzeilige Ausgabe beibehalten mit:
echo "$(ls)"
ls
und mehrzeilige Ausgabe
Sie haben das vielleicht bemerkt ls
manchmal mehr als eine Datei pro Zeile gedruckt wird:
$ ls
file1 file2 file3 file4 file5 file6
Dies ist die Standardeinstellung, wenn die Ausgabe von ls
an ein Terminal gesendet wird. Wenn der Ausgang nicht direkt an ein Terminal geht,ls
wird der Standardwert in eine Datei pro Zeile geändert:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
Dieses Verhalten ist in dokumentiert man ls
.
Eine weitere Subtilität: Befehlsersetzung und nachfolgende Zeilenumbrüche
$(...)
ist die Befehlsersetzung, und die Shell entfernt abschließende Zeilenumbrüche aus der Ausgabe der Befehlsersetzung . Dies ist normalerweise nicht erkennbar, da standardmäßig echo
eine neue Zeile am Ende der Ausgabe eingefügt wird. Wenn Sie also eine neue Zeile am Ende von verlieren und eine davon $(...)
gewinnen echo
, gibt es keine Änderung. Wenn die Ausgabe Ihres Befehls jedoch mit 2 oder mehr Zeilenumbrüchen endet, während echo
nur eines zurückaddiert wird, fehlen in der Ausgabe eine oder mehrere Zeilenumbrüche. Als Beispiel können wir printf
nachfolgende Zeilenumbrüche verwenden. Beachten Sie, dass beide der folgenden Befehle trotz der unterschiedlichen Anzahl von Zeilenumbrüchen dieselbe Ausgabe einer Leerzeile erzeugen:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
Dieses Verhalten ist in dokumentiert man bash
.
Eine weitere Überraschung: die doppelte Erweiterung der Pfadnamen
Lassen Sie uns drei Dateien erstellen:
$ touch 'file?' file1 file2
Beachten Sie den Unterschied zwischen ls file?
und echo $(ls file?)
:
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
Im Fall von echo $(ls file?)
wird der Dateiglob zweimalfile?
erweitert , wodurch die Dateinamen und zweimal in der Ausgabe erscheinen. Dies liegt daran, dass, wie Jeffiekins betont, die Pfadnamenerweiterung zuerst von der Shell ausgeführt wird, bevor sie ausgeführt wird, und dann erneut, bevor sie ausgeführt wird.file1
file2
ls
echo
Die zweite Pfadnamenerweiterung kann unterdrückt werden, wenn wir doppelte Anführungszeichen verwenden:
$ echo "$(ls file?)"
file?
file1
file2