Existe una regla general de almacenamiento en búfer seguida de la biblioteca de E / S estándar C ( stdio
) que utilizan la mayoría de los programas Unix. Si la salida va a un terminal, se vacía al final de cada línea; de lo contrario, se vacía solo cuando el búfer (8K en mi sistema Linux / amd64; podría ser diferente en el suyo) está lleno.
Si todos sus utilidades estaban siguiendo la regla general, que se vería retrasada de salida en todos sus ejemplos ( cat|sed
, cat|tr
y cat|tr|sed
). Pero hay una excepción: GNU cat
nunca amortigua su salida. No se usa stdio
o cambia la stdio
política de almacenamiento en búfer predeterminada .
Puedo estar bastante seguro de que estás usando GNU cat
y no algún otro Unix cat
porque los demás no se comportarían de esta manera. Unix tradicional cat
tiene una -u
opción para solicitar una salida sin búfer. GNU cat
ignora la -u
opción porque su salida siempre está sin búfer.
Entonces, siempre que tenga una tubería con un cat
a la izquierda, en el sistema GNU, el paso de datos a través de la tubería no se retrasará. El cat
ni siquiera se va línea por línea - su terminal está haciendo eso. Mientras escribe la entrada para cat, su terminal está en modo "canónico", basado en líneas, con teclas de edición como retroceso y ctrl-U que le ofrecen la oportunidad de editar la línea que ha escrito antes de enviarla Enter.
En el cat|tr|sed
ejemplo, tr
sigue recibiendo datos cat
tan pronto como presiona Enter, pero tr
sigue la stdio
política predeterminada: su salida se dirige a una tubería, por lo que no se vacía después de cada línea. Escribe en la segunda tubería cuando el búfer está lleno o cuando se recibe un EOF, lo que ocurra primero.
sed
también sigue la stdio
política predeterminada, pero su salida se dirige a un terminal, por lo que escribirá cada línea tan pronto como haya terminado. Esto tiene un efecto sobre cuánto debe escribir antes de que algo aparezca en el otro extremo de la tubería: si sed
bloqueaba su salida, tendría que escribir el doble (para llenar tr
el búfer de salida y sed
la salida de buffer).
GNU sed
tiene la -u
opción, por lo que si invierte el orden y lo usa cat|sed -u|tr
, verá que la salida aparece instantáneamente nuevamente. (La sed -u
opción puede estar disponible en otros lugares, pero no creo que sea una tradición antigua de Unix cat -u
) Hasta donde puedo decir, no hay una opción equivalente para tr
.
Hay una utilidad llamada stdbuf
que le permite alterar el modo de almacenamiento en búfer de cualquier comando que use los stdio
valores predeterminados. Es un poco frágil ya que utiliza LD_PRELOAD
para lograr algo que la biblioteca C no fue diseñada para soportar, pero en este caso parece funcionar:
cat | stdbuf -o 0 tr '[:lower:]' '[:upper:]' | sed 'p'
cat
almacenando en búfer hasta que se cierra la entrada estándar.