Bash
Sostituzione del processo
Ricerca…
Osservazioni
La sostituzione del processo è una forma di reindirizzamento in cui l'input o l'output di un processo (alcune sequenze di comandi) vengono visualizzati come un file temporaneo.
Confronta due file dal web
Quanto segue mette a confronto due file con diff
utilizzando la sostituzione di processo invece di creare file temporanei.
diff <(curl http://www.example.com/page1) <(curl http://www.example.com/page2)
Alimenta un ciclo while con l'output di un comando
Questo alimenta un ciclo while
con l'output di un comando grep
:
while IFS=":" read -r user _
do
# "$user" holds the username in /etc/passwd
done < <(grep "hello" /etc/passwd)
Con comando incolla
# Process substitution with paste command is common
# To compare the contents of two directories
paste <( ls /path/to/directory1 ) <( ls /path/to/directory1 )
Concatenazione di file
È risaputo che non è possibile utilizzare lo stesso file per input e output nello stesso comando. Per esempio,
$ cat header.txt body.txt >body.txt
non fa quello che vuoi Nel momento in cui cat
legge body.txt
, è già stato troncato dal reindirizzamento ed è vuoto. Il risultato finale sarà che body.txt
manterrà solo il contenuto di header.txt
.
Si potrebbe pensare di evitare questo con la sostituzione del processo, cioè il comando
$ cat header.txt <(cat body.txt) > body.txt
costringerà i contenuti originali di body.txt
a essere in qualche modo salvati in qualche buffer da qualche parte prima che il file venga troncato dal reindirizzamento. Non funziona. Il cat
tra parentesi inizia a leggere il file solo dopo che tutti i descrittori di file sono stati impostati, proprio come quello esterno. Non ha senso cercare di utilizzare la sostituzione del processo in questo caso.
L'unico modo per anteporre un file a un altro file è crearne uno intermedio:
$ cat header.txt body.txt >body.txt.new
$ mv body.txt.new body.txt
che è ciò che sed
perl
o programmi simili fanno sotto il tappeto quando vengono chiamati con un'opzione edit-in-place (di solito -i
).
Trasmetti in streaming un file attraverso più programmi contemporaneamente
Conta il numero di linee in un file grande con wc -l
e contemporaneamente lo comprime con gzip
. Entrambi corrono contemporaneamente.
tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Normalmente tee
scrive il suo input su uno o più file (e stdout). Possiamo scrivere sui comandi invece dei file con tee >(command)
.
Qui il comando wc -l >&2
conta le righe lette da tee
(che a sua volta sta leggendo da bigfile
). (Il conteggio delle righe viene inviato a stderr ( >&2
) per evitare di mescolare con l'input a gzip
.) Lo stdout di tee
viene simultaneamente inserito in gzip
.
Per evitare l'uso di una sub-shell
Uno degli aspetti principali della sostituzione del processo è che ci consente di evitare l'utilizzo di una sub-shell durante il piping dei comandi dalla shell.
Questo può essere dimostrato con un semplice esempio qui sotto. Ho i seguenti file nella mia cartella attuale:
$ find . -maxdepth 1 -type f -print
foo bar zoo foobar foozoo barzoo
Se eseguo il pipe su un ciclo while
/ read
che incrementa un contatore come segue:
count=0
find . -maxdepth 1 -type f -print | while IFS= read -r _; do
((count++))
done
$count
ora non contiene 6
, perché è stato modificato nel contesto della sub-shell. Qualsiasi comando mostrato di seguito viene eseguito in un contesto di sub-shell e l'ambito delle variabili utilizzate all'interno viene perso dopo la terminazione della sub-shell.
command &
command | command
( command )
La sostituzione del processo risolverà il problema evitando l'uso del tubo |
operatore come in
count=0
while IFS= read -r _; do
((count++))
done < <(find . -maxdepth 1 -type f -print)
Ciò manterrà il valore della variabile count
quanto non viene invocato alcun sub-shell.