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.