Creé un archivo de prueba llamado 'prueba' que contiene lo siguiente:
xxx
yyy
zzz
Ejecuté el comando:
(sed '/y/ q'; echo aaa; cat) < test
y obtuve:
xxx
yyy
aaa
zzz
Entonces corrí:
cat test | (sed '/y/ q'; echo aaa; cat)
y consiguió:
xxx
yyy
aaa
Pregunta
sedlee e imprime hasta que encuentra una línea con 'y', luego se detiene. En el primer caso, pero no en el segundo, el gato lee e imprime el resto.
¿Alguien puede explicar qué fenómeno está detrás de esta diferencia de comportamiento?
También noté que funciona de esta manera en Ubuntu 16.04 y Centos 6, pero en Centos 7 ninguno de los comandos imprime 'zzz'.

cat(en el sub shell) puede reutilizar el descriptor de archivo en el primer caso, porque stdin está vinculado a un archivo real. En el segundo caso, stdin es de una tubería y no de un archivo real. Tenga en cuenta que(sed '/y/ q'; echo aaa; cat) < <(cat test)tampoco se imprimezzz.(head -n1; head -n1) < testycat test | (head -n1; head -n1)Respuestas:
Cuando el archivo de entrada se puede buscar (como leer desde un archivo normal) o no se puede buscar (como leer desde una tubería),
sed(y otras utilidades estándar) se comportarán de manera diferente (lea laINPUT FILESsección en este enlace ).Cita del documento:
Entonces en:
sedrealizó elqcomando uit antes de llegar a EOF, por lo que dejó el desplazamiento del archivo al comienzo de lazzzlínea, por lo quecatpuede continuar imprimiendo las líneas (GNU sed no es compatible con POSIX en alguna condición, consulte a continuación).Y continuando desde el documento:
En este caso, el comportamiento no está especificado. La mayoría de las herramientas estándar, include
sed, consumirán la entrada tanto como sea posible. Leyó pasar layyylínea yquit sin restaurar el desplazamiento del archivo, por lo que no queda nada paracat.GNU
sedno cumple con el estándar, depende de la implementación estándar del sistema y la versión de glibc:Aquí, el resultado se obtuvo de Mac OSX 10.11.6, máquinas virtuales Centos 7.2 - glibc 2.17, Ubuntu 14.04 - glibc 2.19, que se ejecutan en Openstack con backend CEPH.
En esos sistemas, puede usar la
-uopción para lograr el comportamiento estándar:y para pipa:
lo que conduce a un rendimiento terriblemente ineficiente, porque
sedtiene que leer un byte a la vez. Una salida parcial destrace:fuente
sed, eso depende de la implementación estándar del sistema. En los sistemas GNU (con GNU libc), GNUsedserá compatibleexit()y buscará archivos administrados por stdio.sedno es compatible, mi portátil manjaro sí, todos tienen la mismasedversión 4.2.2strace -f sh -c '{ sed "/y/q"; echo aaa; cat; } <test'demuestro que nolseek()se realizó nada , mientras que en mi manjarolseek()se llamó antesexit_group().main() { char buf[999]; gets(buf); }'programa.