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 tailwird, besteht darin, dass taildie 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 ( teetut dies), sondern die Ausgabe von tailzu erhalten, bevor der Rest des Dokuments ausgegeben wird, ohne eine temporäre Zwischendatei zu verwenden.
Durch die Verwendung sed(oder awkwie bei John1024 ) werden das doppelte Parsen der Daten und das Ordnungsproblem durch Speichern der Daten im Speicher beseitigt .
Die sedLö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.
HFü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 sedund BSD sedmacht).
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 teezum Senden der Daten nach unten mypipeund gleichzeitig an cat. Das catDienstprogramm tailliest zuerst die Ausgabe von (die von liest, von mypipeder geschrieben teewird) 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 teegeschrieben mypipeund catblockiert, während darauf gewartet wird, dass die (unbenannte) Pipe leer wird. Es würde nicht geleert werden, bis es daraus catgelesen wird. catwürde nicht davon lesen, bis tailes fertig war. Und tailwürde nicht fertig werden, bis teefertig war. Dies ist eine klassische Deadlock-Situation.
Die Variation
tee >( tail -n 1 >mypipe ) | cat mypipe -
hat das gleiche Problem.