ich habe das gerade durchgemacht und konnte es nicht verstehen.
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.
wo sich die Cat-Datei befindet:
foo
foo
bar
warum gibt es das 1!H
denn für mich 1h
überschreibt den Musterraum und 1!H
ist nutzlos
Aber der Sed-Einzeiler scheint gut zu funktionieren.
Antwort1
SehenAntwort von @manatworkfür den eigentlichen Grund 1h;1!H
, aber ich wollte einen Hinweis zur Portabilität hinzufügen.
Die standardmäßige und portable Syntax sollte lauten:
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'
Andernfalls funktioniert es in den meisten sed
Implementierungen nicht, beispielsweise in den traditionellen Unix-Implementierungen.
Das wird \n
auf der linken Seite des s
Befehls verstanden, aber Sie müssen auf der rechten Seite einen Backslash gefolgt von einem tatsächlichen Zeilenumbruchzeichen verwenden. Sie benötigen außerdem das ;
zwischen dem s
Befehl und }
und kein Leerzeichen vor dem p
.
Sie können den Inhalt der Datei auch im Musterbereich statt im Haltebereich speichern:
sed -n '
:1
$!{
N;b1
}
s/foo\nbar/blah\
blup/p'
Aber sowohl beim Muster als auch beim Speicherplatz sed
funktioniert das bei den meisten Implementierungen nur mit kleinen Dateien, da die meisten Nicht-GNU-Implementierungen für diese eine begrenzte Größe haben (und POSIX nur erfordert, dass sie 8 KiB Daten speichern können).
Für den mobilen Einsatz sind folgende Methoden besser geeignet perl
:
perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'
Da die Größe in perl
oder GNU nicht begrenzt ist sed
, müssen Sie sich jedoch darüber im Klaren sein, dass dies Auswirkungen auf die Leistung des Systems haben kann, da möglicherweise der gesamte Systemspeicher verwendet wird, wenn Sie keine administrativ festgelegten Grenzen für die Speichernutzung pro Prozess haben.
Antwort2
warum gibt es 1!H, weil für mich 1h den Musterraum überschreibt und 1!H keinen Nutzen hat
Es erfolgt kein Überschreiben, da sie nicht in derselben Eingabezeile ausgeführt werden:
1h # when input line number is 1, copy pattern space to hold space
1!H # when input line number is not 1, append pattern space to hold space
Dies ist notwendig, da info sed
:
`H'
Append a newline to the contents of the hold space, and then
append the contents of the pattern space to that of the hold space.
Wenn Sie also nur H
alle Zeilen anhängen, wird vor der ersten Zeile ein zusätzlicher Zeilenumbruch eingefügt:
bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'
1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3