cat <<EOS | sed -ne '1{h;d;}' -e 'H;${G;p;}'
line 1
line 2
line 3
EOS
Das Problem bei der Übersetzung in etwas, das verwendet tail
wird, besteht darin, dass tail
die gesamte Datei gelesen werden muss, um das Ende zu finden. Um das in Ihrer Pipeline zu verwenden, müssen Sie
- Stellen Sie den vollständigen Inhalt des Dokuments bereit
tail
.
- Stellen Sie es erneut zur Verfügung
cat
.
- In dieser Reihenfolge.
Das schwierige Bit besteht nicht darin, den Inhalt des Dokuments zu duplizieren ( tee
tut dies), sondern die Ausgabe von tail
zu erhalten, bevor der Rest des Dokuments ausgegeben wird, ohne eine temporäre Zwischendatei zu verwenden.
Durch die Verwendung sed
(oder awk
wie bei John1024 ) werden das doppelte Parsen der Daten und das Ordnungsproblem durch Speichern der Daten im Speicher beseitigt .
Die sed
Lösung, die ich vorschlage, ist zu
1{h;d;}
Speichern Sie die erste Zeile unverändert im Haltebereich und fahren Sie mit der nächsten Zeile fort.
H
Fügen Sie einander eine Zeile mit einer eingebetteten neuen Zeile an den Haltebereich an.
${G;p;}
Fügen Sie den Haltebereich mit einer eingebetteten neuen Zeile an die letzte Zeile an und drucken Sie die resultierenden Daten.
Dies ist eine wörtliche Übersetzung der Lösung von John1024 in sed
, mit der Einschränkung, dass der POSIX-Standard nur garantiert, dass der Speicherplatz mindestens 8192 Bytes (8 KiB) beträgt. Es wird jedoch empfohlen , diesen Puffer nach Bedarf dynamisch zuzuweisen und zu erweitern, was beide GNU sed
und BSD sed
macht).
Wenn Sie sich erlauben, eine Named Pipe zu verwenden:
mkfifo mypipe
cat <<EOS | tee mypipe | cat <( tail -n 1 mypipe ) -
line 1
line 2
line 3
EOS
rm -f mypipe
Dies dient tee
zum Senden der Daten nach unten mypipe
und gleichzeitig an cat
. Das cat
Dienstprogramm tail
liest zuerst die Ausgabe von (die von liest, von mypipe
der geschrieben tee
wird) und hängt dann die Kopie des Dokuments an, von der direkt stammt tee
.
Dies ist jedoch ein schwerwiegender Fehler: Wenn das Dokument zu groß ist (größer als die Puffergröße der Pipe), wird in das Dokument tee
geschrieben mypipe
und cat
blockiert, während darauf gewartet wird, dass die (unbenannte) Pipe leer wird. Es würde nicht geleert werden, bis es daraus cat
gelesen wird. cat
würde nicht davon lesen, bis tail
es fertig war. Und tail
würde nicht fertig werden, bis tee
fertig war. Dies ist eine klassische Deadlock-Situation.
Die Variation
tee >( tail -n 1 >mypipe ) | cat mypipe -
hat das gleiche Problem.