¿Cómo pasaría la salida de un comando a múltiples comandos?


20

Usando la sustitución del proceso o agrupando y canalizando, uno puede pasar la salida ( stdout ) un conjunto de comandos como la entrada para otro comando.

Ejemplo:

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

¿Pero hay lo contrario?

Es decir, ¿hay alguna forma de enviar la salida de un comando como entrada para muchos otros comandos en una sola línea ?

Algo como :

cat testfile | wc | tail -n 5

( No tome las tuberías literalmente ). Aquí estoy tratando de pasar la salida de cat testfileambos wcytail -n 5

Otro ejemplo sería:

( para obtener la última palabra de una oración )

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)

Respuestas:


21

Respuesta rápida. Puedes tee >(what_to_do) >(another_thing_to_do)seguir adelante con tu comando para tantas cosas diferentes que quieras hacer.

Ejemplo:

Salida del archivo de prueba original:

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

Salida con teecomandos agregados:

:~$ cat testfile.txt | tee >(tail -1) >(wc) >(awk '{print $3,$1,$2}')
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 en tee son solo comandos normales que usaría en la línea de comandos, como agregar >(head -1 | wc)trabajos también.

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

O también puede tomar la última palabra de decir la última línea mediante el uso awkde $NFuna wc, así como esto:

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

NOTA: Agregar un |comando de tubería al final puede anular el uso de los múltiples comandos del teecomando. Tengo algunos ejemplos aquí que he estado probando:

Ejemplo 1 (comando Pipe que tira de todas las últimas palabras):

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

Ejemplo 2 (No muestra la salida de los comandos wc. Comando Pipe agarrando la tercera palabra):

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

Ejemplo 3 (Agarrando la tercera palabra de la línea de eco. Comando Tee):

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

Ejemplo 4 (Tomando la última palabra de la línea 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 esto ayude!


3
¡Amo la camiseta y el café! '-)
Élder Geek

1
La afirmación sobre el orden de la salida entre los distintos consumidores de teees falsa. La razón por la que generalmente obtiene el pedido correcto es que en una máquina de baja carga, el primer proceso del consumidor se ejecuta primero. En una máquina más ocupada, el primer consumidor podría quedarse dormido antes de que imprima algo.
Matei David el

@MateiDavid No puedo probarlo de otra manera, así que acabo de eliminar la declaración. No es problema.
Terrance

2
Mira mi respuesta. Pero más en serio, teeno tiene idea de los consumidores: son creados por bashquién procesa la línea. Todo lo que bashhace es copiar los descriptores de archivos abiertos. Más allá de eso, hay varios consumidores que escriben en descriptores de archivo abiertos en el mismo archivo. El núcleo se encarga de eso, pero ciertamente el orden en que aparecieron en la bashlínea de comando no será un factor.
Matei David

17

Necesita teedividir la secuencia en partes. Tratar:

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

Notas:

  • Si varios procesos ( wc, tail) están escribiendo en stdout:

    • Puede obtener resultados confusos.

    • No hay garantía sobre el orden en que aparecerá su salida. Para ver esto, intente sleep 1; wc -wcomo el segundo consumidor.

  • teese bloqueará si alguno de sus destinos no consume la transmisión lo suficientemente rápido. Es decir, los destinos se alimentarán a una velocidad aproximadamente similar (módulo de almacenamiento en búfer de tamaño fijo). No hay una solución fácil para esto, la única alternativa es guardar la secuencia en un archivo y enviarla a los consumidores por separado. Para wcy tailesto no es un problema.

Para la última palabra, es más simple de hacer:

echo "some random words" | awk '{print $NF}'

5

El moreutilspaquete proporciona el comando pee(fusión de pipe y tee, ¿qué pensaste?) Que hace exactamente eso.

Para su primer ejemplo, usaría:

cat testfile | pee wc "tail -n 5"

El segundo ejemplo es más complicado porque desea pasar dos entradas al último comando. Probablemente lo usaría awkcomo las otras respuestas.

Enlace: https://joeyh.name/code/moreutils/

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.