Bash
Procesvervanging
Zoeken…
Opmerkingen
Procesvervanging is een vorm van omleiding waarbij de invoer of uitvoer van een proces (een reeks opdrachten) wordt weergegeven als een tijdelijk bestand.
Vergelijk twee bestanden van internet
Het volgende vergelijkt twee bestanden met diff
met behulp van procesvervanging in plaats van tijdelijke bestanden te maken.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Voer een while-lus in met de uitvoer van een opdracht
Dit voedt een while
lus met de uitvoer van een grep
opdracht:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Met plakopdracht
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Bestanden samenvoegen
Het is bekend dat u niet hetzelfde bestand kunt gebruiken voor invoer en uitvoer in dezelfde opdracht. Bijvoorbeeld,
$ cat header.txt body.txt >body.txt
doet niet wat je wilt. Tegen de tijd dat cat
body.txt
leest, is het al afgekapt door de omleiding en is het leeg. Het uiteindelijke resultaat is dat body.txt
alleen de inhoud van header.txt
.
Je zou kunnen denken om dit te vermijden met procesvervanging, dat wil zeggen dat het commando
$ cat header.txt <(cat body.txt) > body.txt
zal de originele inhoud van body.txt
op een of andere manier ergens in een buffer opslaan voordat het bestand wordt afgekapt door de omleiding. Het werkt niet. De cat
tussen haakjes begint het bestand pas te lezen nadat alle bestandsdescriptors zijn ingesteld, net als de buitenste. In dit geval heeft het geen zin om te proberen procesvervanging te gebruiken.
De enige manier om een bestand voor te bereiden op een ander bestand is om een tussenliggend bestand te maken:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
dat is wat sed
of perl
of vergelijkbare programma's onder het tapijt doen wanneer ze worden aangeroepen met een optie voor bewerken op de plaats (meestal -i
).
Stream een bestand door meerdere programma's tegelijk
Dit telt het aantal regels in een groot bestand met wc -l
terwijl het tegelijkertijd wordt gecomprimeerd met gzip
. Beide lopen tegelijkertijd.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Normaal schrijft tee
zijn invoer naar een of meer bestanden (en stdout). We kunnen schrijven naar opdrachten in plaats van bestanden met tee >(command)
.
Hier telt het commando wc -l >&2
de regels die worden gelezen van tee
(die op zijn beurt van bigfile
). (Het aantal regels wordt verzonden naar stderr ( >&2
) om te voorkomen dat er wordt gemengd met de invoer naar gzip
.) De stdout van tee
wordt tegelijkertijd in gzip
ingevoerd.
Om het gebruik van een sub-shell te voorkomen
Een belangrijk aspect van procesvervanging is dat we hiermee het gebruik van een sub-shell kunnen vermijden bij het piping-commando's van de shell.
Dit kan worden aangetoond met een eenvoudig voorbeeld hieronder. Ik heb de volgende bestanden in mijn huidige map:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Als ik naar een while
/ read
lus pijp, wordt de teller als volgt opgehoogd:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
nu doet bevatten 6
, omdat het in de sub-shell context is aangepast. Alle onderstaande opdrachten worden uitgevoerd in een context van een subshell en het bereik van de gebruikte variabelen gaat verloren nadat de subshell wordt beëindigd.
command &
command | command
( command )
Procesvervanging lost het probleem op door het gebruik van de van pipe |
vermijden operator als in
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Hierdoor blijft de waarde van de count
behouden omdat er geen sub-shells worden aangeroepen.