Meine Frage bezieht sich auf den sed -spezifische Lösung, die in dieser Antwort für diese Frage des Reverse Grepping angegeben ist. Der sed /grep Lösung, die ich nicht entziffern kann, ist die folgende:
sed '1!G;h;$!d' file
Kann bitte jemand diesen Befehl entziffern?
Ich weiß aus VI(M)-Wissen, dass G die letzte Zeile der Datei bezeichnet und dass in sed ein Knall(!) gefolgt von einer Adresse ein bisschen wie grep -v funktioniert das heißt, es wird nicht mit dieser Zeile übereinstimmen. Aber als Ganzes ist mir das obige Inline-sed-Skript ein Rätsel.
Akzeptierte Antwort:
Dies kehrt die Datei Zeile für Zeile um.
sed '1!G;h;$!d' file
Zuerst sed hat ein Haltefeld und ein Musterraum . Wir müssen zwischen ihnen unterscheiden, bevor wir uns auf diesen speziellen Befehl konzentrieren.
Wenn sed liest eine neue Zeile, wird sie in den Musterbereich geladen. Daher wird dieser Speicherplatz jedes Mal überschrieben, wenn eine neue Zeile verarbeitet wird. Andererseits ist der Haltebereich über die gesamte Verarbeitung konsistent und Werte können dort für eine spätere Verwendung gespeichert werden.
Zum Befehl:
Es gibt 3 Befehle in dieser Anweisung:1!G , h und $!d
-
1!Gbedeutet, dass dasGBefehl wird in jeder Zeile außer der ersten ausgeführt (der!negiert die1).Gbedeutet anhängen was sich im Haltebereich befindet, in den Musterbereich. -
hgilt für jede Zeile. Es kopiert den Musterbereich in den Haltebereich (und überschreibt ihn). -
$!dgilt für jede Zeile außer der letzten ($stellt die letzte Zeile dar,!negiert es).dist der Befehl zum Löschen der Zeile (Musterraum).
- Nun, wenn die erste Zeile gelesen wird,
sedführt dashaus Befehl. Die erste Zeile wird in den Haltebereich kopiert. Dann wird er gelöscht, da er mit$!übereinstimmt Zustand.sedfährt mit der zweiten Zeile fort. - Die zweite Zeile entspricht der Bedingung
1!(es ist nicht die erste Zeile), und so wird der Halteraum (der die erste Zeile hat) an den Musterraum (der die zweite Zeile hat) angehängt. Danach folgt im Musterbereich nun die zweite Zeile, gefolgt von der ersten Zeile, die durch einen Zeilenumbruch begrenzt ist. Jetzt dashBefehl gilt (wie in jeder Zeile); Alles, was sich im Musterbereich befindet, wird in den Haltebereich kopiert. Die dritte Anweisung ($!d) gilt:Die Linie wird aus dem Musterbereich gelöscht. - Schritt 2 ist nun mit allen Linien erledigt. Wir springen zur letzten Zeile.
- In der letzten Zeile (
$) ist fast der gesamte Schritt 2 erledigt, aber nicht der Löschteil (d).sed, wenn es ohne-naufgerufen wird , druckt den Musterraum automatisch am Ende der Verarbeitung für jede Eingabezeile. Wenn er also nicht gelöscht wird, wird der Musterbereich gedruckt. Es enthält nun alle Zeilen in umgekehrter Reihenfolge .