Quando il file di input è ricercabile (come la lettura da un file normale) o non ricercabile (come la lettura da una pipe), sed(e altre utilità standard) si comporteranno in modo diverso (Leggi la INPUT FILESsezione in questo link ).
Citazione dal documento:
Quando un'utilità standard legge un file di input ricercabile e termina senza errori prima che raggiunga la fine del file, l'utilità deve assicurarsi che l'offset del file nella descrizione del file aperto sia posizionato correttamente dopo l'ultimo byte elaborato dall'utilità.
Quindi in:
(sed '/y/ q'; echo aaa; cat) < test
sedeseguito il qcomando uit prima di raggiungere EOF, quindi ha lasciato l'offset del file all'inizio della zzzlinea, quindi catpuò continuare a stampare le linee rimanenti (GNU sed non è conforme POSIX in alcune condizioni, vedere sotto).
E proseguendo dal documento:
Per i file non ricercabili, lo stato dell'offset del file nella descrizione del file aperto per quel file non è specificato
In questo caso, il comportamento non è specificato. La maggior parte degli strumenti standard, include sedconsumerà l'input il più possibile. Legge passare la yyylinea e quit senza ripristinare l'offset del file, quindi nulla è lasciato per cat.
GNU sednon è conforme allo standard, dipende dall'implementazione stdio del sistema e dalla versione glibc:
$ (gsed '/y/ q'; echo aaa; cat) < test
xxx
yyy
aaa
Qui, il risultato è stato ottenuto da Mac OSX 10.11.6, macchine virtuali Centos 7.2 - glibc 2.17, Ubuntu 14.04 - glibc 2.19, che vengono eseguiti su Openstack con backend CEPH.
Su tali sistemi, è possibile utilizzare l' -uopzione per ottenere il comportamento standard:
(gsed -u '/y/ q'; echo aaa; cat) </tmp/test
e per tubo:
$ cat test | (gsed -u '/y/ q'; echo aaa; cat)
xxx
yyy
aaa
zzz
che porta a prestazioni terribilmente inefficienti, perché seddeve leggere un byte alla volta. Un output parziale da strace:
$ strace -fe read sh -c '{ sed -u "/y/q"; echo aaa; cat; } <test'
...
[pid 5248] read(3, "", 4096) = 0
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
xxx
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
yyy
...
cat(nella sotto shell) possa riutilizzare il descrittore di file nel primo caso, perché stdin è associato a un file reale. Nel secondo caso, stdin proviene da una pipe e non da un file reale. Si noti che anche(sed '/y/ q'; echo aaa; cat) < <(cat test)non stampazzz.