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 FILES
sezione 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
sed
eseguito il q
comando uit prima di raggiungere EOF, quindi ha lasciato l'offset del file all'inizio della zzz
linea, quindi cat
può 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 sed
consumerà l'input il più possibile. Legge passare la yyy
linea e q
uit senza ripristinare l'offset del file, quindi nulla è lasciato per cat
.
GNU sed
non è 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' -u
opzione 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é sed
deve 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
.