Meine Frage bezieht sich auf die sed
spezifische Lösung, die in dieser Antwort für diese Frage des umgekehrten Greppings angegeben ist . Die sed
/ grep
-Lösung, die ich nicht entziffern kann, ist die folgende:
sed '1!G;h;$!d' file
Kann jemand bitte diesen Befehl entschlüsseln?
Ich weiß aus VI (M) -Wissen, dass G die letzte Zeile der Datei bezeichnet und dass in sed ein Knall (!) Gefolgt von einer Adressarbeit ein bisschen bedeutet grep -v
, dass es nicht zu dieser Zeile passt. Aber als Ganzes ist das Inline-Sed-Skript über mir.
sed
Rezept eine äußerst ineffiziente Methode (O (n ^ 2/2) -Komplexität) ist, um Zeilen in einer Datei umzukehren. Es wäre unerschwinglich langsam für Dateien mit einer großen Anzahl von Zeilen. Eine viel effizientere Alternative zur Umkehrung der Zeilenreihenfolge finden Sietac
in GNU coreutils.Antworten:
Dies kehrt die Datei zeilenweise um.
Erstens
sed
hat ein Hold-Space und ein Pattern-Space . Wir müssen sie unterscheiden, bevor wir uns auf diesen speziellen Befehl konzentrieren.Wenn
sed
eine neue Zeile gelesen wird, wird sie in den Musterraum geladen. Daher wird dieser Speicherplatz jedes Mal überschrieben, wenn eine neue Zeile verarbeitet wird. Auf der anderen Seite ist der Speicherplatz über die gesamte Verarbeitung konsistent und die Werte können dort zur späteren Verwendung gespeichert werden.Zum Befehl:
Es gibt 3 Befehle in dieser Aussage:
1!G
,h
und$!d
1!G
bedeutet, dass derG
Befehl in jeder Zeile außer der ersten ausgeführt wird (die!
negiert die1
).G
Mittel zum anhängen , was im Laderaum in den Musterraum ist.h
gilt für jede Zeile. Es kopiert den Pattern-Space in den Hold-Space (und überschreibt ihn).$!d
gilt für jede Zeile mit Ausnahme der letzten ($
stellt die letzte Zeile dar,!
negiert sie).d
ist der Befehl zum Löschen der Zeile (Musterabstand).sed
wird derh
Befehl ausgeführt. Die erste Zeile wird in den Laderaum kopiert. Dann wird es gelöscht, da es der$!
Bedingung entspricht.sed
fährt mit der zweiten Zeile fort.1!
(es ist nicht die erste Zeile), und daher wird der Haltebereich (der die erste Zeile enthält) an den Musterbereich (der die zweite Zeile enthält) angehängt. Danach folgt im Musterraum die zweite Zeile, gefolgt von der ersten Zeile, die durch eine neue Zeile begrenzt wird. Jetzt gilt derh
Befehl (wie in jeder Zeile); Alles, was sich im Pattern-Space befindet, wird in den Hold-Space kopiert. Die dritte Anweisung ($!d
) gilt: Die Zeile wird aus dem Musterbereich gelöscht.$
) ist fast alles von Schritt 2 erledigt, nicht jedoch der Löschteil (d
).sed
Wenn diese Option ohne aufgerufen wird-n
, wird der Musterbereich am Ende der Verarbeitung für jede Eingabezeile automatisch gedruckt. Wenn dies nicht gelöscht wird, wird der Musterbereich gedruckt. Es enthält nun alle Zeilen in umgekehrter Reihenfolge .quelle
h
Befehl kopiert den Musterbereich in den Haltebereich, der bis zumsed
Ende bestehen bleibt . Nach dem Ende des Skripts wird alles gelöscht, da die Binärdatei beendet wird.sed
gibt es nur einen Laderaum. Es ist wie eine Variable, die etwas enthalten kann.-n
wir jede Zeile mit Ausnahme der letzten löschen. In der letzten Zeile hängt sed alles vom Hold-Raum bis zum Pattern-Raum an. Und weil derd
Befehl nicht ausgeführt wird, wird die Zeile gedruckt (diese Zeile enthält jetzt die gesamte Datei in umgekehrter Reihenfolge).h
Befehl in der letzten Zeile ist also eine Art No-Op.“ (Mit zusätzlicher Betonung und leicht umschrieben). Er hat recht; Wennsed
die letzte Eingabezeile verarbeitet wird ,G
liest der den Haltebereich (um ihn an den Musterbereich anzuhängen) undh
kopiert dann den Musterbereich in den Haltebereich, auf den nie wieder verwiesen wird . Wir könnten genauso gut sagensed 'G;$!h;$!d'
odersed 'G;$!{h;d}'
. (2) Wir könnten vermeiden,d
indem wir sagensed -n 'G;h;$p'
.