|
sed der "stream editor"
Viele Daten, Konfigurationsdateien oder auch Mess- oder Zugriffsprotokolle
enthalten die Nutzinformation für bestimmte Auswertungen nicht in der
optimalen Form. Mit sed steht ein sehr leistungsfähiges Werkzeug zur
Verfügung, um die Daten geeignet aufzubereiten.
Grundlagen
Adressierung
Viele Befehle erlauben das Voranstellen der Zeilen, auf die der Befehl
angewendet werden soll. 1,$p führt von der ersten bis
zur letzten Zeile ($ ) den Befehl p aus.
1p;$p führt den Befehl für die erste und die letzte
Zeile aus.
Statt der Zeilennummer können auch Suchmuster angegeben werden.
/Start/,$p führt den Befehl p ab der ersten
Zeile, die Start enthält bis zur letzten Zeile aus.
Komplexe Bedingungen lassen sich mit Sprüngen im Skript lesbar realisieren.
1b first
2,$p
d
:first
${s/^/Nur eine einzige Zeile: /;p;d}
p
In diesem Beispiel wird eine Sonderbehandlung für die erste Zeile ab
dem Label first durchgeführt. Hier wird eine Regel für
die letzte Zeile umgesetzt, die dann im Gesamtkontext nur ausgeführt wird,
wenn die erste auch die letzte Zeile ist.
Mehrzeilige Opererationen (s.u.) erfordern oft eine Sonderbehandlung der ersten,
oder letzten Zeile. Dieses ist mit den Sprüngen leicht möglich.
Puffer
sed verfügt über zwei Puffer. Der "pattern space" ist derjenige,
mit dem die meisten Operationen durchgeführt werden. Zusätzlich
gibt des den "hold space", der als Zwischenspeicher genutzt werden kann.
Die Puffer können vertauscht, ersetzt und verkettet werden und bieten
somit komplexe Möglichkeiten. Ein entstehendes Risiko ist, dass
zwischengespeicherte Informationen beim Erreichen der letzten Zeile nicht
mehr ausgegeben werden; hier ist besondere Vorsicht bei der Erstellung des
Skripts erforderlich.
x | Austausch der Puffer |
h | Ersetze hold space durch den Inhalt des pattern space |
H | Hänge pattern space an hold space an. Die Zeilenenden bleiben dabei erhalten und müssen bei Bedarf entfernt werden. |
g | Ersetze pattern space durch den Inhalt des hold space |
G | Hänge hold space an pattern space an. Die Zeilenenden bleiben dabei erhalten und müssen bei Bedarf entfernt werden. |
Zeilen in umgekehrter Reihenfolge ausgeben
Mit diesem kurzen Skript 1!G;h;$!d werden die Eingangszeilen
in umgekehrter Folge ausgegeben. Erklärung: Alle Zeilen werden im hold
space gesammelt; mit G wird an jede neue Zeile der bestehende
hold space angehängt. Für die erste Zeile ergibt das keinen Sinn;
für diese wird mit h der hold space durch den pattern space
ersetzt.
Dieses erfolgt für die anderen Zeilen nach dem Verketten ebenfalls, so dass
sowohl im hold space, als auch im pattern space immer alle Zeilen enthalten
sind.
Jetzt wird mit d die nächste Zeilenverarbeitung
angestoßen. Einzige Ausnahme ist die letzte Zeile. Da kein expliziter
Befehl für diese Zeile vorhanden ist, wird der pattern space ausgegeben.
Dieser enthät die Eingangsdaten in umgekehrter Reihenfolge.
Verbinden mehrere Zeilen
Liegen zusammengehörige Informationen in mehreren aufeinanderfolgenden
Zeile vor, ist es häufig sinnvoll diese in eine Zeile zu verbinden,
Folgeoperationen zeilenbasiert durchzuführen und ggf. anschließend wieder die
alte mehrzeilige Form wiederherzustellen. Für den hier skizzierten Weg
mit sed ist es erforderlich die jeweils zusammenhängenden Daten formal
beschreiben, bzw. erkennen zu können.
Leerzeilen als Trennung
Eingangsdaten:
----- snip -----
1. Zeile
2. Zeile
4. Zeile
5. Zeile
----- snip -----
Skript:
sed -n '/^[ \t]*$/{x;s/\n/|/g;s/^|//;P;D};${H;x;s/\n/|/g;s/^|//;P};{H}'
oder als Skript-Datei:
/^[ \t]*$/{x;s/\n/|/g;s/^|//;P;D}
${H;x;s/\n/|/g;s/^|//;P}
{H}
Ausgangsdaten:
----- snip -----
1. Zeile|2. Zeile
4. Zeile|5. Zeile
----- snip -----
Erklärung: Zu Beginn wird die Erkennung eines neuen Blocks bearbeitet.
Alle Zeilen, die nur aus white space bestehen /^[ \t]*$/ als
Kriterium. Dieses kann dann leicht an andere Gegebenheiten angepasst werden.
Jetzt wird der hold space geholt (x ),
die Zeilenumbrüche gewandelt (s/\n/|/g ),
der Zeilenanfang korrigiert (s/^|// ),
gedruckt P und der pattern space gelöscht (D ).
Als Nächstes wird die letzte Zeile behandelt:
pattern space an den hold space anhängen H ,
die Zeilenumbrüche gewandelt (s/\n/|/g ),
der Zeilenanfang korrigiert (s/^|// ) und
gedruckt P .
Zum Abschluss erfolgt die Abarbeitung der restlichen Zeilen; hier nur die
Verkettung der beiden Puffer (H );
die Klammern könnten entfallen.
INI-Dateien
Eingangsdaten:
----- snip -----
[section 1]
a=a
b=b
[section 2]
c=c
d=d
[section 3]
[section 4]
----- snip -----
Skript als Skript-Datei:
${s/\([[].*[]]\)/\1/;t new;H;x;s/\n/|/g;s/^|//;P}
1{h;D}
/^[[].*[]]$/{x;s/\n/|/g;s/^|//;P;D}
{H}
d
:new
{x;s/\n/|/g;s/^|//;P;x;P}
Ausgangsdaten:
----- snip -----
[section 1]|a=a|b=b
[section 2]|c=c|d=d
[section 3]
[section 4]
----- snip -----
Erklärung:
Das Skript beginnt mit der Regel für die letzte Zeile. Da hier
eine unterschiedliche Behandlung erforderlich ist, je nachdem, ob ein neuer
Block beginnt oder nicht erfolgt ein Test auf einen neuen Block mit einem
bedingten Sprung zum Label :new (s/\([[].*[]]\)/\1/;t new; ).
Der pattern space bleibt dabei unverändert. Wenn es eine Folgezeile
ist, erfolgt die bekannte Abarbeitung: An hold space anhängen, tauschen,
Zeilenenden ersetzen und ausgeben. Wenn es ein neuer Block war, dann wird
erst der hold space aufbereitet, ausgegeben und im Anschluss die aktuelle
Zeile zurückgeholt und ausgegeben. Wenn die Eingabe nur aus einer
einzigen Zeile besteht, dann wird durch die Ausgabe des hold space vor der
Ausgabe der letzten Zeile in der Ausgabe eine Leerzeile erzeugt.
|