Como eu passaria a saída de um comando para vários comandos?

15

Usando a substituição de processos ou agrupando & amp; canalização, pode-se passar a saída ( stdout ) um conjunto de comandos como a entrada para outro comando.

Exemplo:

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

Mas existe o oposto?

Ou seja, existe uma maneira de enviar a saída de um comando como a entrada para muitos outros comandos em uma linha única ?

Algo como:

cat testfile | wc | tail -n 5

( Não use pipelines literalmente ). Aqui estou tentando passar a saída de cat testfile para wc e tail -n 5

Outro exemplo seria:

( para obter a última palavra de uma frase )

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

3 respostas

19

Resposta rápida. Você pode usar tee >(what_to_do) >(another_thing_to_do) para continuar com seu comando para quantas coisas diferentes quiser fazer.

Exemplo:

Saída do arquivo de teste original:

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

Saída com os comandos tee adicionados:

:~$ 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

Cada comando no tee é apenas um comando normal que você usaria na linha de comando, como adicionar >(head -1 | wc) também.

:~$ 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

Ou você também pode pegar a última palavra da última linha, usando awk com $NF com wc , assim:

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

NOTA: A adição de um comando | pipe ao final pode substituir usando os vários comandos do comando tee . Eu tenho alguns exemplos aqui que tenho testado:

Exemplo 1 (comando Pipe puxando todas as últimas palavras):

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

Exemplo 2 (Não mostra a saída dos comandos wc. Comando Pipe pegando a terceira palavra.):

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

Exemplo 3 (Agarrando a terceira palavra da linha de 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

Exemplo 4 (Agarrando a última palavra da linha de 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

Espero que isso ajude!

    
por Terrance 04.10.2016 / 20:47
17

Você precisa de tee para dividir o fluxo em partes. Experimente:

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

Notas:

  • Se vários processos ( wc , tail ) forem todos gravados no stdout:

    • Você pode receber impressões ilegíveis.

    • Não há garantia sobre a ordem em que sua saída será exibida. Para ver isso, tente sleep 1; wc -w como o segundo consumidor.

  • tee será bloqueado se algum dos seus destinos não consumir o fluxo com rapidez suficiente. Ou seja, os destinos serão alimentados com uma velocidade aproximadamente similar (módulo de buffer de tamanho fixo). Não há uma solução fácil para isso, a única alternativa é salvar o fluxo em um arquivo e fornecê-lo aos consumidores separadamente. Para wc e tail , isso não é um problema.

Para a última palavra, é mais simples de fazer:

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

O pacote moreutils fornece o comando pee (mesclagem de pipe e tee, o que você achou?) que faz exatamente isso.

Para o seu primeiro exemplo, você usaria:

cat testfile | pee wc "tail -n 5"

O segundo exemplo é mais complicado porque você quer passar duas entradas para o último comando. Eu provavelmente usaria awk como as outras respostas.

Link: link

    
por T. Verron 05.10.2016 / 09:57