Come potrei passare l'output di un comando a più comandi?

15

Usare la sostituzione di processo o raggruppando & amp; piping, si può passare l'output ( stdout ) un insieme di comandi come input per un altro comando.

Esempio:

wc < <(echo hi;echo bye)
(echo hi; bye) | wc

Ma c'è il contrario?

Cioè, c'è un modo per inviare l'output di un comando come input per molti altri comandi in una singola riga ?

Qualcosa come:

cat testfile | wc | tail -n 5

( Non prendere letteralmente le pipeline ). Qui sto cercando di passare l'output di cat testfile a entrambi wc e tail -n 5

Un altro esempio potrebbe essere:

( per ottenere l'ultima parola di una frase )

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)
    
posta Severus Tux 04.10.2016 - 20:29

3 risposte

19

Risposta rapida. Puoi utilizzare tee >(what_to_do) >(another_thing_to_do) per andare avanti con il tuo comando per tutte le cose che vuoi fare.

Esempio:

Output del file di test originale:

:~$ cat testfile.txt 
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616

Output con tee comandi aggiunti:

:~$ cat testfile.txt | tee >(tail -1) >(wc) >(awk '{print ,,}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
      2      10      91
Serial Number:    TW0XFJWX550854187616

Ogni comando in tee è solo un normale comando che useresti sulla riga di comando, come anche l'aggiunta in >(head -1 | wc) .

:~$ cat testfile.txt | tee >(tail -1) >(head -1 | wc)  >(awk '{print ,,}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
      1       7      52
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
Serial Number:    TW0XFJWX550854187616

Oppure puoi anche prendere l'ultima parola di dire l'ultima riga usando awk con $NF con wc così come questo:

:~$ cat testfile.txt | tail -1 | tee >(wc) >(awk '{print $NF}')
Serial Number:    TW0XFJWX550854187616
TW0XFJWX550854187616
      1       3      39

NOTA: l'aggiunta di un comando pipe | alla fine può eseguire l'override utilizzando più comandi dal comando tee . Ho alcuni esempi qui che ho provato:

Esempio 1 (comando Pipe che tira tutte le ultime parole):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $NF}'
words
24
5
1

Esempio 2 (Non mostra l'output dei comandi wc. Il comando pipe cattura la 3a parola.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print }'
just

Esempio 3 (Afferrare la terza parola della linea dell'eco. Comando Tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print }')
This is just five words
just
24
5
1

Esempio 4 (Afferrando l'ultima parola della linea dell'eco. Comando Tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $NF}')
This is just five words
words
24
5
1

Spero che questo aiuti!

    
risposta data Terrance 04.10.2016 - 20:47
17

Hai bisogno di tee per dividere il flusso in parti. Prova:

cat testfile | tee >(wc -l) >(wc -w) >(wc -c) | tail -n 5

Note:

  • Se più processi ( wc , tail ) stanno scrivendo tutti su stdout:

    • Potresti ottenere un output confuso.

    • Non esiste alcuna garanzia sull'ordine in cui apparirà il loro output. Per vedere questo, prova sleep 1; wc -w come secondo consumatore.

  • tee bloccherà se una delle sue destinazioni non consuma il flusso abbastanza velocemente. Significa che le destinazioni verranno alimentate in ingresso a una velocità approssimativamente simile (modulo il buffering a dimensione fissa). Non esiste una soluzione semplice per questo, l'unica alternativa è salvare il flusso in un file e inviarlo separatamente ai consumatori. Per wc e tail questo non è un problema.

Per l'ultima parola, è più semplice da fare:

echo "some random words" | awk '{print $NF}'
    
risposta data Matei David 04.10.2016 - 20:43
3

Il pacchetto moreutils fornisce il comando pee (unione di pipe e tee, cosa ne pensi?) che fa esattamente questo.

Per il tuo primo esempio, devi utilizzare:

cat testfile | pee wc "tail -n 5"

Il secondo esempio è più complicato perché vuoi passare due input all'ultimo comando. Probabilmente userò awk come le altre risposte.

Link: link

    
risposta data T. Verron 05.10.2016 - 09:57

Leggi altre domande sui tag