Ich bin verwirrt von den beiden Konzepten in sed: Hold Space und Pattern Space. Kann jemand helfen, sie zu erklären?
Hier ist ein Ausschnitt aus dem Handbuch:
h H Copy/append pattern space to hold space. g G Copy/append hold space to pattern space. n N Read/append the next line of input into the pattern space.
Diese sechs Befehle verwirren mich wirklich.
echo $'1\n2\n3\n4' | sed -n '1~2h;2~2{p;x;p}'
info sed
. Es ist viel detaillierter als die bloße Manpage.Antworten:
Wenn Sed liest eine Datei Zeile für Zeile, die Zeile , die in den eingeführt ist derzeit gelesen wurde Musterpuffer (Musterraum). Der Musterpuffer ist wie der temporäre Puffer, das Notizbuch, auf dem die aktuellen Informationen gespeichert sind. Wenn Sie sed anweisen, zu drucken, wird der Musterpuffer gedruckt.
Hold Buffer / Hold Space ist wie ein Langzeitspeicher, sodass Sie etwas abfangen, speichern und später wiederverwenden können, wenn sed eine andere Zeile verarbeitet. Sie verarbeiten den Haltebereich nicht direkt, sondern müssen ihn kopieren oder an den Musterbereich anhängen, wenn Sie etwas damit tun möchten. Beispielsweise
p
druckt der Druckbefehl nur den Musterbereich. Ebensos
arbeitet auf dem Musterraum.Hier ist ein Beispiel:
(Die Option -n unterdrückt das automatische Drucken von Zeilen.)
Hier gibt es drei Befehle :
1!G
,h
und$p
.1!G
hat eine Adresse1
(erste Zeile), aber das!
bedeutet, dass der Befehl überall ausgeführt wird, außer in der ersten Zeile.$p
Auf der anderen Seite wird nur in der letzten Zeile ausgeführt. Was also passiert, ist Folgendes:h
kopiert die erste Zeile in den Haltebereich .G
, wobei der Inhalt des Haltepuffers an den Musterpuffer angehängt und durch eine neue Zeile getrennt wird. Der Musterbereich enthält jetzt die zweite Zeile, eine neue Zeile und die erste Zeile.h
fügt der Befehl den verketteten Inhalt des Musterpuffers in den Haltebereich ein, der nun die umgekehrten Zeilen zwei und eins enthält.Nachdem die letzte Zeile gelesen und der Haltebereich (der alle vorherigen Zeilen in umgekehrter Reihenfolge enthält) an den Musterbereich angehängt wurde, wird der Musterbereich mit gedruckt
p
. Wie Sie vermutet haben, macht das Obige genau das, was dertac
Befehl tut - druckt die Datei in umgekehrter Reihenfolge.quelle
'195,210{/add/p}'
… Ist es möglich, die letzte Zeile einer Gruppe von Zeilen zu extrahieren, die an einem Muster beteiligt sind?@ Ed Morton: Ich stimme dir hier nicht zu. Ich fand es
sed
sehr nützlich und einfach (sobald Sie das Konzept des Musters verstanden haben und Puffer halten), eine elegante Methode für das mehrzeilige Greppen zu finden.Nehmen wir zum Beispiel eine Textdatei mit Hostnamen und einigen Informationen zu jedem Host, mit viel Müll dazwischen, den ich nicht interessiere.
Für mich würde ein awk-Skript, um nur die Zeilen mit dem Hostnamen und der entsprechenden
info
Zeile abzurufen, etwas mehr dauern, als ich mit sed tun kann:Ausgabe sieht aus wie:
(Beachten Sie, dass dies
Host: foo1
in der Ausgabe zweimal vorkommt.)Erläuterung:
-n
Deaktiviert die Ausgabe, sofern nicht ausdrücklich gedrucktHost:
Zeile in den Haltepuffer (h)Host:
ausgetauscht und die Zeile gedruckt (p) . Anschließend wird die Info: -Zeile erneut ausgetauscht (x) und gedruckt (p).Ja, dies ist ein vereinfachtes Beispiel, aber ich vermute, dass dies ein häufiges Problem ist, das von einem einfachen Einzeiler schnell behoben wurde. Für viel komplexere Aufgaben, bei denen Sie sich nicht auf eine bestimmte, vorhersehbare Reihenfolge verlassen können, ist awk möglicherweise besser geeignet.
quelle
grep 'Host\|Info'
awk
Äquivalent Ihres sed-Codes ist auch ziemlich kurz:awk '/Host:/{hold=$0}; /Info/{print hold; print;}' myfile.txt
Obwohl die Antwort von @ January und das Beispiel nett sind, hat mir die Erklärung nicht gereicht. Ich musste viel suchen und lernen, bis ich verstanden hatte, wie genau das
sed -n '1!G;h;$p'
funktioniert. Deshalb möchte ich den Befehl für jemanden wie mich näher erläutern.Lassen Sie uns zunächst sehen, was der Befehl bewirkt.
Es kehrt die Eingabe um, wie es der
tac
Befehl tut.sed
Liest Zeile für Zeile, also lasst uns sehen, was auf dem Patten- und dem Haltebereich in jeder Zeile passiert . Wenn derh
Befehl den Inhalt des Musterbereichs in den Haltebereich kopiert, haben beide Bereiche denselben Text.In der letzten Zeile
$p
drucktd\nc\nb\na$
, die formatiertWenn Sie den Musterbereich für jede Zeile anzeigen möchten, können Sie einen
l
Befehl hinzufügen .Ich fand es sehr hilfreich, dieses Video-Tutorial zu sehen. Verstehen, wie sed funktioniert , da der Typ zeigt, wie jeder Raum Schritt für Schritt verwendet wird. Der Abstand zum Halten wird im 4. Tutorial beschrieben. Ich empfehle jedoch, alle Videos anzusehen, wenn Sie nicht mit diesen vertraut sind
sed
.Auch das Sed-Dokument von GNU und das Sed-Tutorial von Bruce Barnett sind sehr gute Referenzen.
quelle