Betrachten Sie die beiden Shell-Beispiele
$ ls
myDoc.html
SomeDirectory
someDoc.txt
und
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
Der erste ls
Befehl wird ausgeführt und hängt, wie ich weiß, den Inhalt des aktuellen Arbeitsverzeichnisses an die stdout
Datei an (was das Terminal anzeigt). Ist das richtig?
Der zweite ls
Befehl übernimmt den Wert des Befehls (dh den Inhalt des aktuellen Arbeitsverzeichnisses) und druckt ihn in die stdout
Datei. Ist das richtig?
Warum geben die beiden Befehle unterschiedliche Ausgaben aus?
ls
Sie nicht mehrere Artikel pro Zeile erhalten?echo *
?Antworten:
Wenn Sie diesen Befehl ausführen:
Das Terminal zeigt die Ausgabe von an
ls
.Wenn Sie diesen Befehl ausführen:
Die Shell erfasst die Ausgabe von
$(ls)
und führt eine Wortteilung durch . StandardmäßigIFS
bedeutet dies, dass alle Folgen von Leerzeichen, einschließlich Zeilenumbrüchen, durch ein einzelnes Leerzeichen ersetzt werden. Deshalbecho $(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:
ls
und mehrzeilige AusgabeSie haben das vielleicht bemerkt
ls
manchmal mehr als eine Datei pro Zeile gedruckt wird: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: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äßigecho
eine neue Zeile am Ende der Ausgabe eingefügt wird. Wenn Sie also eine neue Zeile am Ende von verlieren und eine davon$(...)
gewinnenecho
, gibt es keine Änderung. Wenn die Ausgabe Ihres Befehls jedoch mit 2 oder mehr Zeilenumbrüchen endet, währendecho
nur eines zurückaddiert wird, fehlen in der Ausgabe eine oder mehrere Zeilenumbrüche. Als Beispiel können wirprintf
nachfolgende Zeilenumbrüche verwenden. Beachten Sie, dass beide der folgenden Befehle trotz der unterschiedlichen Anzahl von Zeilenumbrüchen dieselbe Ausgabe einer Leerzeile erzeugen:Dieses Verhalten ist in dokumentiert
man bash
.Eine weitere Überraschung: die doppelte Erweiterung der Pfadnamen
Lassen Sie uns drei Dateien erstellen:
Beachten Sie den Unterschied zwischen
ls file?
undecho $(ls file?)
: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:
quelle
isatty
Sie überprüfen , ob stdout ein tty ist, verwendet ls dies fest , ob die Farben oder nicht zu ermitteln.$( )
tatsächlich eine Syntaxbarriere, damit Sie nicht interpolieren müssen?$()
bietet eine Syntaxbarriere.echo
Befehl das Platzhalterzeichen . Zum Beispiel, wennls
die Datei zurückgegeben wird? Datei1 Datei2 , dannecho $(ls)
wird die Datei zurückgegeben? Datei1 Datei2 Datei1 Datei2 .echo
erweitert keine Platzhalter; Die Shell führt dies aus, bevor die resultierende Erweiterung als Argumente an übergeben wirdecho
.ls
ist sich bewusst, ob eine Ausgabe an ein Terminal gesendet wird oder nicht.Das Ausführen
ls
an einer Eingabeaufforderung schreibt in Ihre Pseudotty. Das Umleiten der Ausgabe vonls
wird im Allgemeinen nicht zu einer Pseudo-Tty führen undls
die Ausgabe anders formatieren.quelle