Anwendungsfall für sed: ein Muster suchen, um die vorhergehende Zeile zu ändern

Peter Voigt peter.voigt1 at gmx.net
Fr Jul 8 18:08:56 CEST 2011


Hallo,

gestern tauchte in der Lugrav die Frage auf, ob es mittels sed möglich ist, eine
Zeile zu ändern, falls die *folgende* Zeile ein bestimmtes Suchmuster aufweist.

Ad hoc vorgeschlagen wurden Lösungen mittels tac, grep, awk und ed.


Mit sed läßt sich das Problem mit dem geringsten Aufwand an Rechenzeit lösen 
unter Ausnutzung eines Features, welches als Holdspace bezeichnet wird:


   sed -n '/muster_danach/{G;/muster_darin/s/alt_text/neu_text/p;};h' eingabedatei


Dieser Befehl ersetzt den Ausdruck 'alt_text' durch den Ausdruck 'neu_text', 

   genau dann, falls die folgende Zeile das Suchmuster '/muster_folgezeile/' 

   und falls die betroffene Zeile das Suchmuster '/muster_darin/' enthält.


Das Suchmuster '/muster_darin/' kann fortfallen, wenn man es nicht braucht.


Zur Erläuterung: Bei dem Holdspace handelt sich um einen simplen Zwischen-
speicher, der mit dem Befehl 'h' beschrieben und dem Befehl 'G' gelesen
wird.


Der Einzeiler unterscheidet zwei Fälle:

(1) Zunächst schaut sed, ob die gerade zu verarbeitende Zeile das Suchmuster 
/muster_danach/ enthält. Falls nein, überspringt sed die Klammerung und geht 
direkt zum Befehl 'h', um die aktuelle Zeile im Zwischenspeicher abzulegen.

(2) Falls die aktuelle Zeile das Suchmuster doch enthält, verarbeitet sed
die Befehle innerhalb der Klammern. Zuerst ruft sed mittels 'G' die zuletzt 
abgespeicherte Zeile wieder auf. Danach führt sed eine ganz normale Sub-
stitution mittels 's' durch, dessen Ergebnis dann ausgedruckt wird. Nach 
dem Abarbeiten der Befehle in der Klammer geht es hinter der Klammer weiter, 
d.h. mittels 'h' wird die aktuelle Zeile in den Zwischenspeicher geschoben. 


Zusammengefaßt: Jede Zeile kommt in den Zwischenspeicher, egal ob sie das
Suchmuster enthält oder nicht. Wenn das Suchmuster in der Zeile  auftaucht, 
wird zusätzlich die vorhergehende Zeile aus dem Zwischenspeicher zurückgeholt, 
wie gewünscht verändert und ausgegeben.


Die Klammerung mit dem vorangehenden Suchmuster wirkt wie eine If-then-Klausel. 

In der Klammer werden nur solche Zeilen aus der Eingabedatei verarbeitet, die 
das voranstehende Suchmuster erfüllen. Hinter der schliessenden Klammer hat 
dieses Suchmuster keine Bedeutung mehr. Weil dem 'h' keine Suchmaske voran-
steht, wird das 'h' auf jede Zeile der Eingabedatei angewendet.

Das letzte ';' vor der schliessenden Klammer ist aus syntaktischen Gründen 
notwendig, sonst kommt es zur Fehlermeldung.  


Anmerkung: Ich habe den Einzeiler unter der BSD-Variante von sed getestet, 
die Linux-Variante sollte ebenso funktionieren ;) 

pv



 


Mehr Informationen über die Mailingliste Lugrav