Explicación simplificada
Al igual que muchas utilidades, esto no es algo peculiar de un programa, grep
varía su salida estándar entre estar en línea y completamente en memoria intermedia . En el primer caso, la biblioteca C almacena en memoria intermedia los datos de salida en la memoria hasta que se llena el búfer que contiene esos datos o se agrega un carácter de salto de línea (o el programa finaliza limpiamente), por lo que llama write()
para escribir realmente el contenido del búfer. En el último caso, solo el búfer en memoria que se llena (o el programa termina limpiamente) activa el write()
.
Explicación más detallada
Esta es la explicación bien conocida, pero ligeramente incorrecta. De hecho, la salida estándar no es amortiguada línea, pero inteligente amortiguada en la biblioteca GNU C y C biblioteca de BSD. La salida estándar también se vacía cuando la lectura de la entrada estándar agota su búfer en memoria (de entrada previa a la lectura) y la biblioteca C tiene que llamar read()
para obtener más entrada y está leyendo el comienzo de una nueva línea. (Una razón para esto es evitar el punto muerto cuando otro programa se conecta a ambos extremos de un filtro y espera poder operar línea por línea, alternando entre escribir en el filtro y leerlo; como "coprocesos" en GNU awk
por ejemplo.)
Influencia de la biblioteca C
grep
y las otras utilidades hacen esto, o más estrictamente, las bibliotecas C que usan hacen esto, porque esta es una característica definida de programación en el lenguaje C, en función de lo que detectan que es su salida estándar. Si (y solo si) no es un dispositivo interactivo, eligen el almacenamiento en búfer completo, de lo contrario eligen el almacenamiento en búfer inteligente. Se considera que una tubería no es un dispositivo interactivo, porque la definición de ser un dispositivo interactivo, al menos en el mundo de Unix y Linux, es esencialmente la isatty()
devolución de la llamada verdadera para el descriptor de archivo relevante.
Soluciones para deshabilitar el almacenamiento en búfer completo
Algunas utilidades como grep
tienen opciones idiosincrásicas como --line-buffered
que cambian esta decisión, que como puede ver está mal nombrada. Pero una fracción cada vez más pequeña de los programas de filtro que uno podría usar realmente tiene esa opción.
En términos más generales, se pueden usar herramientas que profundizan en los componentes internos específicos de la biblioteca C y cambian su toma de decisiones (que tienen problemas de seguridad si el programa que se va a modificar es set-UID, y también son específicos de bibliotecas C particulares, y de hecho son específico para programas escritos o en capas sobre el lenguaje C), o herramientas como esas ptybandage
que no cambian las partes internas del programa sino que simplemente interponen un pseudo-terminal como salida estándar para que la decisión salga como "interactiva", para afectar esto
Otras lecturas
cat
concatena archivos ¿Qué estás tratando de hacer entrandocat
?