cat <<EOS | sed -ne '1{h;d;}' -e 'H;${G;p;}'
line 1
line 2
line 3
EOS
Il problema con la traduzione di questo in qualcosa che utilizza tailè che è tailnecessario leggere l'intero file per trovarne la fine. Per usarlo nella tua pipeline, devi farlo
- Fornire l'intero contenuto del documento a
tail.
- Forniscilo di nuovo a
cat.
- In questo ordine.
Il trucco non è duplicare il contenuto del documento (lo teefa) ma ottenere l'output di tailavvenire prima che venga emesso il resto del documento, senza usare un file temporaneo intermedio.
L'utilizzo sed(o awk, come fa John1024 ) elimina la doppia analisi dei dati e il problema di ordinazione memorizzando i dati in memoria.
La sedsoluzione che propongo è
1{h;d;}, archivia la prima riga nello spazio di attesa, così com'è, e passa alla riga successiva.
H, aggiungere ogni altra riga allo spazio di attesa con una nuova riga incorporata.
${G;p;}, aggiungi lo spazio di conservazione all'ultima riga con una nuova riga incorporata e stampa i dati risultanti.
Questa è una traduzione letterale della soluzione di John1024 in sed, con l'avvertenza che lo standard POSIX garantisce solo che lo spazio di attesa sia almeno 8192 byte (8 KiB; ma raccomanda che questo buffer sia allocato dinamicamente ed espanso secondo necessità, che entrambi GNU sede BSD sedsta facendo).
Se ti permetti di usare una pipa denominata:
mkfifo mypipe
cat <<EOS | tee mypipe | cat <( tail -n 1 mypipe ) -
line 1
line 2
line 3
EOS
rm -f mypipe
Questo utilizza teeper inviare i dati verso il basso mypipee, allo stesso tempo per cat. L' catutilità leggerà prima l'output da tail(che legge da mypipe, che teesta scrivendo), quindi aggiungerà la copia del documento proveniente direttamente da tee.
C'è però un grave difetto in questo, nel senso che se il documento è troppo grande (più grande della dimensione del buffer della pipe), sta teescrivendo mypipee catsi bloccherebbe in attesa che la pipe (senza nome) si svuoti. Non verrebbe svuotato fino a quando non verrà catletto. catnon avrebbe letto da esso fino a quando non tailfosse terminato. E tailnon sarebbe finito fino a quando non teefosse finito. Questa è una classica situazione di deadlock.
La variazione
tee >( tail -n 1 >mypipe ) | cat mypipe -
ha lo stesso problema.