Se esperaba que el siguiente comando de shell imprimiera solo líneas impares de la secuencia de entrada:
echo -e "aaa\nbbb\nccc\nddd\n" | (while true; do head -n 1; head -n 1 >/dev/null; done)
Pero en vez de eso sólo imprime la primera línea: aaa
.
No ocurre lo mismo cuando se usa con la opción -c
( --bytes
):
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 >/dev/null; done)
Este comando sale 1234512345
como se esperaba. Pero esto solo funciona en la implementación de coreutils de la head
utilidad. La implementación de busybox todavía consume caracteres adicionales, por lo que la salida es justa 12345
.
Supongo que esta forma específica de implementación se realiza con fines de optimización. No puede saber dónde termina la línea, por lo que no sabe cuántos caracteres necesita leer. La única forma de no consumir caracteres adicionales de la secuencia de entrada es leer la secuencia byte por byte. Pero leer de la transmisión un byte a la vez puede ser lento. Supongo que head
lee el flujo de entrada en un búfer lo suficientemente grande y luego cuenta las líneas en ese búfer.
No se puede decir lo mismo del caso cuando --bytes
se usa la opción. En este caso, usted sabe cuántos bytes necesita leer. Entonces puede leer exactamente este número de bytes y no más que eso. La implementación de corelibs usa esta oportunidad, pero la busybox no, todavía lee más bytes de los necesarios en un búfer. Probablemente se haga para simplificar la implementación.
Entonces la pregunta. ¿Es correcto que la head
utilidad consuma más caracteres de la secuencia de entrada de los que se le pidió? ¿Existe algún tipo de estándar para las utilidades de Unix? Y si lo hay, ¿especifica este comportamiento?
PD
Debe presionar Ctrl+C
para detener los comandos anteriores. Las utilidades de Unix no fallan al leer más allá EOF
. Si no desea presionar, puede usar un comando más complejo:
echo 12345678901234567890 | (while true; do head -c 5; head -c 5 | [ `wc -c` -eq 0 ] && break >/dev/null; done)
que no usé por simplicidad.