Was ist der Unterschied zwischen <<
, <<<
und < <
in bash?
command-line
bash
redirect
Searene
quelle
quelle
Antworten:
Hier dokumentieren
<<
ist alshere-document
Struktur bekannt. Sie lassen das Programm wissen, was der Endtext sein wird, und wann immer dieses Trennzeichen angezeigt wird, liest das Programm alle Informationen, die Sie dem Programm als Eingabe gegeben haben, und führt eine Aufgabe darauf aus.Folgendes meine ich:
In diesem Beispiel weisen wir das
wc
Programm an, auf eineEOF
Zeichenfolge zu warten , dann fünf WörterEOF
einzugeben und anschließend zu signalisieren, dass die Eingabe abgeschlossen ist. In der Tat ist es ähnlich, als würde manwc
von selbst laufen , Wörter eingeben und dann drückenCtrlDIn der Bash werden diese über temporäre Dateien implementiert, normalerweise in der Form
/tmp/sh-thd.<random string>
, während sie in Strichen als anonyme Pipes implementiert werden. Dies kann über Tracing-Systemaufrufe mitstrace
Befehl beobachtet werden . Ersetzen Siebash
durch, umsh
zu sehen, wie/bin/sh
diese Umleitung ausgeführt wird.Hier String
<<<
ist bekannt alshere-string
. Anstatt Text einzugeben, geben Sie einem Programm eine vorgefertigte Textfolge. Mit einem solchen Programm, wiebc
wir es tun können,bc <<< 5*4
um nur die Ausgabe für diesen speziellen Fall zu erhalten, muss bc nicht interaktiv ausgeführt werden.Hier werden Zeichenfolgen in bash über temporäre Dateien implementiert, in der Regel im Format
/tmp/sh-thd.<random string>
, die später nicht verknüpft werden. Dadurch belegen sie vorübergehend Speicherplatz, werden jedoch nicht in der Liste der/tmp
Verzeichniseinträge angezeigt und existieren effektiv als anonyme Dateien, die möglicherweise noch vorhanden sind Der Dateideskriptor wird von der Shell selbst über den Dateideskriptor referenziert. Dieser Dateideskriptor wird vom Befehl geerbt und später über diedup2()
Funktion auf den Dateideskriptor 0 (stdin) dupliziert . Dies kann über beobachtet werdenUnd über Tracing-Systemaufrufe (Ausgabe aus Gründen der Lesbarkeit gekürzt; beachten Sie, wie temporäre Dateien als fd 3 geöffnet werden, Daten darauf geschrieben werden, dann mit dem
O_RDONLY
Flag fd 4 erneut geöffnet werden und später die Verknüpfungdup2()
auf fd 0 aufheben, diecat
später vererbt wird ):Meinung: Da Zeichenfolgen hier möglicherweise temporäre Textdateien verwenden, ist dies der mögliche Grund, warum Zeichenfolgen hier immer eine abschließende neue Zeile einfügen, da die Textdatei nach POSIX-Definition Zeilen haben muss, die mit einem Zeilenumbruch enden.
Prozessersetzung
Wie tldp.org erklärt,
Tatsächlich ist dies also vergleichbar mit der Weiterleitung von stdout von einem Befehl zum anderen, z
echo foobar barfoo | wc
. Beachten Sie jedoch : In der bash-Manpage sehen Sie, dass es als gekennzeichnet ist<(list)
. Grundsätzlich können Sie also die Ausgabe mehrerer (!) Befehle umleiten.Hinweis: Wenn Sie sagen, dass
< <
Sie sich nicht auf eine Sache beziehen, sondern auf zwei Umleitungen mit Einzel-<
und Prozessumleitung der Ausgabe von<( . . .)
.Was passiert nun, wenn wir nur die Substitution durchführen?
Wie Sie sehen, erstellt die Shell einen temporären Dateideskriptor,
/dev/fd/63
in dem die Ausgabe gespeichert wird (was laut Gilles 'Antwort eine anonyme Pipe ist). Das bedeutet,<
dass der Dateideskriptor als Eingabe in einen Befehl umgeleitet wird.Ein sehr einfaches Beispiel wäre, die Ausgabe von zwei Echo-Befehlen durch einen Prozess in wc zu ersetzen:
Hier lassen wir die Shell einen Dateideskriptor für alle Ausgaben in Klammern erstellen und leiten diese als Eingabe an.
wc
Wie erwartet empfängt wc diesen Stream von zwei Echo-Befehlen, die für sich genommen zwei Zeilen mit jeweils einem Wort ausgeben. und passend haben wir 2 Wörter, 2 Zeilen und 6 Zeichen plus zwei gezählte neue Zeilen.Randnotiz : Die Prozessersetzung kann als Bashismus bezeichnet werden (ein Befehl oder eine Struktur, die in fortgeschrittenen Shells verwendet werden kann
bash
, aber nicht von POSIX angegeben wurde), wurde jedochksh
vor der Bash-Existenz als ksh-Manpage implementiert und diese Antwort schlägt vor. Shells mögentcsh
und habenmksh
jedoch keine Prozessersetzung. Wie können wir also die Ausgabe mehrerer Befehle in einen anderen Befehl umleiten, ohne den Prozess zu ersetzen? Gruppierung plus Verrohrung!Tatsächlich ist dies dasselbe wie im obigen Beispiel. Dies unterscheidet sich jedoch unter der Haube von der Prozessersetzung, da wir die gesamte Unterschale und
wc
die mit dem Rohr verbundene Länge ausfüllen . Auf der anderen Seite bewirkt die Prozessersetzung, dass ein Befehl einen temporären Dateideskriptor liest.Wenn wir also eine Gruppierung mit Rohrleitungen durchführen können, warum brauchen wir dann eine Prozessersetzung? Weil wir manchmal keine Rohrleitungen verwenden können. Betrachten Sie das folgende Beispiel - Vergleichen der Ausgaben von zwei Befehlen mit
diff
(für die zwei Dateien erforderlich sind, und in diesem Fall geben wir zwei Dateideskriptoren an).quelle
< <
wird verwendet, wenn eine Prozessersetzung stdin liefert . Ein solcher Befehl aussehen könnte:cmd1 < <(cmd2)
. Zum Beispielwc < <(date)
< <
ist keine Sache für sich, im Falle einer Prozesssubstitution<
folgt lediglich etwas anderes, das gerade beginnt<
<<<
wurde es zuerst von der Unix-Portierung von Plan 9 RC-Shell implementiert und später von zsh, bash und ksh93 übernommen. Ich würde es dann nicht einen Bashismus nennen.echo 'foo' | read; echo ${REPLY}
Wird nicht zurückgegebenfoo
, da sieread
in einer Unterschale gestartet werden - Pipes starten eine Unterschale. Wird jedochread < <(echo 'foo'); echo ${REPLY}
korrekt zurückgegebenfoo
, da keine Unterschale vorhanden ist.< <
ist ein Syntaxfehler:< <()
ist Prozessersetzung (<()
) kombiniert mit Umleitung (<
):Ein ausgedachtes Beispiel:
Bei der Prozessersetzung wird der Pfad zum Dateideskriptor wie ein Dateiname verwendet. Wenn Sie einen Dateinamen nicht direkt verwenden möchten (oder können), kombinieren Sie die Prozessersetzung mit der Umleitung.
Klar, es gibt keinen
< <
Operator.quelle
<()
gibt eine dateinamenähnliche Sache an, daher ist es im Allgemeinen nützlich< <()
, das Standardverzeichnis dort zu ersetzen, wo es möglicherweise nicht erforderlich ist. Inwc
geschieht letzteres mehr nützlich zu sein. Es könnte an anderer Stelle weniger nützlich sein< <
Wenn es sich um einen Syntaxfehler handelt, meinen Sie wahrscheinlich, dasscommand1 < <( command2 )
dies eine einfache Eingabeumleitung gefolgt von einer Prozessersetzung ist, die sehr ähnlich, aber nicht äquivalent ist zu:Der Unterschied, vorausgesetzt Sie laufen,
bash
wirdcommand1
im zweiten Fall in einer Subshell ausgeführt, während er im ersten Fall in der aktuellen Shell ausgeführt wird. Das bedeutet, dass die eingegebenen Variablencommand1
bei der Prozessersetzungsvariante nicht verloren gehen.quelle
< <
wird einen Syntaxfehler geben. Die bestimmungsgemäße Verwendung ist wie folgt:Erklären anhand von Beispielen:
Beispiel für
< <()
:Im obigen Beispiel stammt die Eingabe für die while-Schleife von dem
ls
Befehl, der zeilenweise gelesen undecho
in der Schleife bearbeitet werden kann.<()
wird für die Prozesssubstitution verwendet. Weitere Informationen und Beispiele<()
finden Sie unter diesem Link:Prozessersetzung und Rohrleitung
quelle