Bash
Prozessersetzung
Suche…
Bemerkungen
Prozessersetzung ist eine Form der Umleitung, bei der die Eingabe oder Ausgabe eines Prozesses (eine bestimmte Befehlsfolge) als temporäre Datei angezeigt wird.
Vergleichen Sie zwei Dateien aus dem Web
Im Folgenden werden zwei Dateien mit diff
Verwendung der Prozessersetzung verglichen, anstatt temporäre Dateien zu erstellen.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Führen Sie eine while-Schleife mit der Ausgabe eines Befehls aus
Dies führt eine while
Schleife mit der Ausgabe eines grep
Befehls aus:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Mit dem Einfügen-Befehl
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Verketten von Dateien
Es ist bekannt, dass Sie nicht dieselbe Datei für Eingabe und Ausgabe in demselben Befehl verwenden können. Zum Beispiel,
$ cat header.txt body.txt >body.txt
tut nicht was du willst Zu dem Zeitpunkt, an dem cat
body.txt
liest, wurde es bereits von der Umleitung abgeschnitten und ist leer. Das Endergebnis wird sein, dass body.txt
nur den Inhalt von header.txt
.
Man könnte denken, dies zu vermeiden, indem man den Prozess ersetzt, dh den Befehl
$ cat header.txt <(cat body.txt) > body.txt
zwingt den ursprünglichen Inhalt von body.txt
, irgendwo in einem Puffer body.txt
zu werden, bevor die Datei durch die Umleitung abgeschnitten wird. Es geht nicht. Die cat
in Klammern beginnt erst dann mit dem Lesen der Datei, nachdem alle Dateideskriptoren eingerichtet wurden, genau wie der äußere. Es hat keinen Sinn, in diesem Fall die Prozessersetzung zu verwenden.
Die einzige Möglichkeit, eine Datei einer anderen Datei voranzustellen, ist das Erstellen einer Zwischendatei:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
sed
ist, was sed
oder perl
oder ähnliche Programme unter dem Teppich machen, wenn sie mit einer Edit-In-Place- Option aufgerufen werden (normalerweise -i
).
Streamen Sie eine Datei gleichzeitig durch mehrere Programme
Dies zählt die Anzahl der Zeilen in einer großen Datei mit wc -l
während sie gleichzeitig mit gzip
. Beide laufen gleichzeitig.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Normalerweise schreibt tee
seine Eingabe in eine oder mehrere Dateien (und stdout). Mit tee >(command)
können Sie anstelle von Dateien in Befehle schreiben.
Hier zählt der Befehl wc -l >&2
die von tee
gelesenen Zeilen (die wiederum von bigfile
). (Die Zeilenzahl wird an stderr ( >&2
) gesendet, um ein Vermischen mit dem Eingang zu gzip
zu vermeiden.) Das stdout von tee
wird gleichzeitig in gzip
.
Um die Verwendung einer Sub-Shell zu vermeiden
Ein wesentlicher Aspekt der Prozessersetzung ist, dass wir die Verwendung einer Sub-Shell beim Piping von Befehlen aus der Shell vermeiden können.
Dies kann unten anhand eines einfachen Beispiels demonstriert werden. Ich habe die folgenden Dateien in meinem aktuellen Ordner:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Wenn ich zu einer while
/ read
Schleife pfeife, wird der Zähler wie folgt inkrementiert:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
jetzt nicht 6
, da es im Sub-Shell-Kontext geändert wurde. Alle unten gezeigten Befehle werden in einem Sub-Shell-Kontext ausgeführt. Der Gültigkeitsbereich der darin verwendeten Variablen geht nach dem Beenden der Sub-Shell verloren.
command &
command | command
( command )
Prozess Substitution wird das Problem lösen , indem das Rohr zu vermeiden verwenden |
Betreiber wie in
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Dadurch wird der Wert der count
beibehalten, da keine Subshells aufgerufen werden.