Bash
Processersättning
Sök…
Anmärkningar
Processersättning är en form av omdirigering där inmatningen eller utdata från en process (viss sekvens med kommandon) visas som en tillfällig fil.
Jämför två filer från webben
Följande jämför två filer med diff
hjälp av processersättning istället för att skapa tillfälliga filer.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Mata en stundslinga med utgången från ett kommando
Detta matar en while
slinga med utgången av en grep
kommando:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Med klistra in kommando
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Sammanfoga filer
Det är välkänt att du inte kan använda samma fil för att mata in och mata ut i samma kommando. Till exempel,
$ cat header.txt body.txt >body.txt
gör inte vad du vill. När cat
läser body.txt
har den redan trunkerats av omdirigeringen och den är tom. Det slutliga resultatet blir att body.txt
innehåller innehållet i header.txt
.
Man kan tänka sig undvika detta med processersättning, det vill säga att kommandot
$ cat header.txt <(cat body.txt) > body.txt
kommer att tvinga det ursprungliga innehållet i body.txt
att på något sätt sparas i någon buffert någonstans innan filen trunkeras av omdirigeringen. Det fungerar inte. cat
inom parentes börjar läsa filen först efter att alla filbeskrivningar har ställts in, precis som den yttre. Det är ingen mening att försöka använda processersättning i detta fall.
Det enda sättet att förbereda en fil till en annan fil är att skapa en mellanliggande:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
vilket är vad sed
eller perl
eller liknande program gör under mattan när de kallas med ett edit-in-place- alternativ (vanligtvis -i
).
Strömma en fil genom flera program på en gång
Detta räknar antalet rader i en stor fil med wc -l
samtidigt som det komprimeras med gzip
. Båda körs samtidigt.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Normalt skriver tee
sin inmatning till en eller flera filer (och stdout). Vi kan skriva till kommandon istället för filer med tee >(command)
.
Här räknar kommandot wc -l >&2
raderna som läses från tee
(som i sin tur läser från bigfile
). (Linjeräkningen skickas till stderr ( >&2
) för att undvika blandning med ingången till gzip
.) Stdout för tee
matas samtidigt in i gzip
.
För att undvika användning av ett underskal
En viktig aspekt av processersättning är att det låter oss undvika användning av ett sub-shell när vi rör kommandon från skalet.
Detta kan demonstreras med ett enkelt exempel nedan. Jag har följande filer i min nuvarande mapp:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Om jag rör till en while
/ read
slingan som ökar en räknare enligt följande:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
innehåller nu inte 6
, eftersom det modifierades i sub-shell-sammanhanget. Några av kommandona som visas nedan körs i ett sub-shell-sammanhang och räckvidden för de variabler som används inom går förlorade efter att sub-skalet upphör.
command &
command | command
( command )
Processersättning kommer att lösa problemet genom att undvika att använda röret |
operatör som i
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Detta behåller count
eftersom inga underskal anropas.