Mehrfache Standardeingabe? Wie?

36

Von diesem Kommandozeilenbeitrag :

$ diff <(wget -q -O - URL1) <(wget -q -O - URL2)

Scheint wie mehrere Standardeingaben, aber --- wenn ich mich richtig an meinen Linux-Programmierkurs erinnere --- kann das nicht sein. Ich dachte, dass die Standardeingabe per Definition ein Stream ist.

Vielleicht hat das ja was mit stdin zu tun? Kann mir jemand das erklären; Stellen Sie möglicherweise Links zur Dokumentation bereit.

Bonus: Wie würde ein Skript mit diesen mehreren Streams umgehen? Wenn jemand ein Python- oder Perl-Beispiel bereitstellen könnte, wäre das sehr hilfreich.

Belmin Fernandez
quelle
1
Gute Frage. Falls Sie es nicht wissen, gibt es eine Unix / Linux-Q & A-Site: unix.stackexchange.com
Matt Ellen
2
Dokumentation für Prozessersetzungen: gnu.org/software/bash/manual/bashref.html#Process-Substitution
Glenn Jackman
Hinweis: In Bash ist es <(…); in Zsh Prozesssubstitutionssyntax ist =(…).
Kamil Maciorowski

Antworten:

27

Dies ist keine mehrfache Standardeingabe. Dies ist ein Bash'ismus, der als "Prozessersetzung" bezeichnet wird ( http://tldp.org/LDP/abs/html/process-sub.html)

/dev/fd/somethingFür jede Ersetzung wird eine Pseudodatei ( ) erstellt. Das ist ziemlich nützlich. Der Befehl kann nur als Stream gelesen werden, dh er kann nicht mit fseek hin und her gehen. Es muss als ein Strom von Bytes wie eine Pipe gelesen werden.

BONUS Antwort

Sie müssen nicht zu viel tun, um dies zu nutzen. Für Ihr Skript wird in der Befehlszeile ein gültiger Dateiname angezeigt, der wie alles andere auch open () ed sein kann. Wie andere gesagt haben, würden Sie sehen diff /dev/fd/XX /dev/fd/YY. Wenn Sie stat () für eine dieser Pseudodateien ausführen, werden Sie feststellen, dass es sich um eine Named Pipe handelt, und Sie sollten sie mit Pipe-Semantik behandeln, dh ohne fseek () oder ftell (). Wenn Sie einen stat () -Test durchführen, um explizit zu prüfen, ob es sich um eine Datei handelt (z. B. [ -f $1 ]), wird diese nicht mehr funktionieren - sie wird schließlich als Named Pipe implementiert.

Reiche Homolka
quelle
Eine weitere gute Referenz für bash Prozess Substitution - wiki.bash-hackers.org/syntax/expansion/proc_subst
studgeek
Und wie wird diese Funktion empfohlen? Unterstützen Sie es, wenn Ihr Programm vernünftigerweise mit einem Stream arbeiten könnte, anstatt eine Datei mit wahlfreiem Zugriff zu benötigen?
Masterxilo
7

<(...)tut Prozess Substitution in bash. Die Ausgabe des Prozesses in den Parens wird an einen zusätzlichen Dateideskriptor gesendet, der über die normale Zahl 3 hinausgeht, und ein Dateiname wird entsprechend diesem Dateideskriptor zurückgegeben. Auf diese Weise kann die Ausgabe eines Befehls als Dateiname behandelt werden, der an einen anderen Befehl übergeben wird.

Ignacio Vazquez-Abrams
quelle
7

Es gibt eins stdinund eins stdout für jeden Prozess . Sie sind normalerweise mit dem Terminal verbunden, können jedoch getrennt voneinander umgeleitet werden.

Im Beispiel handelt es sich um zwei wgetProzesse, von denen jeder seinen eigenen stdinund einen eigenen erhält stdout. Jeder wgetProzess schreibt an -, welches sein ist stdout. Dann bash‚s Prozess Substitution <(...)verbindet die stdoutdes Prozesses zu einer einzigartigen pseudo-Datei, aus dem diffgelesen werden kann. Beachten Sie, dass die beiden Prozessersetzungen zwei verschiedene Pseudodateien ergeben! So diffsieht so etwas aus:

diff /dev/fd/XX /dev/fd/YY

wo das stdoutvon wget -q -O - URL1verbunden ist /dev/fd/XX, und das stdoutvon wget -q -O - URL2zu /dev/fd/YY.

musiphil
quelle