Si solo desea la primera o dos líneas, el siguiente tipo de truco funciona y evita los problemas de almacenamiento en búfer causados por el uso de dos comandos diferentes para leer la secuencia de salida:
$ ps -eF | { IFS= read -r x ; echo "$x" ; grep worker; }
$ ls -la / | { IFS= read -r x ; echo "$x" ; grep sbin; }
El read
está integrado en el shell y no consume un búfer completo de entrada solo para generar una línea, por lo que el uso read
deja todo el resto de la salida para el siguiente comando.
Si desea acentuar los problemas de almacenamiento en búfer que muestran sus ejemplos que usan dos comandos diferentes, agréguelos sleep
a ellos para eliminar los problemas de sincronización y permita que el comando de la izquierda genere toda su salida antes de que los comandos de la derecha intenten leer cualquiera de eso:
$ ps -eF | { sleep 5 ; head -n 1 ; grep worker; }
$ ls -la / | { sleep 5 ; head -n 1 ; grep sbin; }
Ahora, los dos ejemplos anteriores fallan de la misma manera: head
lee un búfer completo de la salida solo para producir una línea, y ese búfer no está disponible para lo siguiente grep
.
Puede ver el problema del almacenamiento en búfer aún más claramente utilizando algunos ejemplos que numeran las líneas de salida para que pueda saber qué líneas faltan:
$ ps -eF | cat -n | { sleep 5 ; head -n 1 ; head ; }
$ ls -la /usr/bin | cat -n | { sleep 5 ; head -n 1 ; head ; }
Una forma sencilla de ver el problema del almacenamiento en búfer es utilizar seq
un generador de una lista de números. Podemos decir fácilmente qué números faltan:
$ seq 1 100000 | { sleep 5 ; head -n 1 ; head ; }
1
1861
1862
1863
1864
1865
1866
1867
1868
1869
Mi solución truco usando el shell para leer y hacer eco de la primera línea funciona correctamente incluso con el retraso de sueño agregado:
$ seq 1 100000 | { sleep 5 ; IFS= read -r x ; echo "$x" ; head ; }
1
2
3
4
5
6
7
8
9
10
11
A continuación se muestra un ejemplo completo que muestra los head
problemas de almacenamiento en búfer, que muestra cómo
head
consume un búfer completo de la salida solo para producir sus cinco líneas cada vez. Ese búfer consumido no está disponible para el siguiente
head
comando en la secuencia:
$ seq 1 100000 | { sleep 5 ; head -5 ; head -5 ; head -5 ; head -5 ; }
1
2
3
4
5
1861
1862
1863
1864
499
3500
3501
3502
3503
7
5138
5139
5140
5141
Mirando el número 1861
anterior, podemos calcular el tamaño del búfer que se utiliza head
contando la seq
salida de 1
a
1860
:
$ seq 1 1860 | wc -c
8193
Vemos que head
se almacena en búfer leyendo 8 KB completos (8 * 1024 bytes) de la salida de la tubería a la vez, incluso para producir solo unas pocas líneas de su propia salida.
head
ygrep
no hacer nada allí.