Eine der häufigsten Aufgaben eines Scripts ist die Veränderung (Editierung) eines Datenstroms. Dabei ist es – wie immer bei Linux/Unix – unerheblich, ob der Datenstrom eine Datei oder eine Ausgabe eines Programms ist. Zu diesem Zweck gibt es den Stream-Editor sed, der einen solchen Datenstrom nach bestimmten Regeln verändert. Die Regeln werden dabei entweder auf der Kommandozeile mitgegeben, oder über eine separate Datei, die sogenannte Script-Datei.

Verallgemeinert können wir sagen, dass sed ein Programm ist, das seine Standard-Eingabe nach eben diesen Regeln verändert (editiert) und sie dann auf die Standard-Ausgabe ausgibt.

Die Form der Scripts ähnelt im Großen und Ganzen den Befehlen des alten Editors ed. Nur dass im Gegensatz zu ed bei sed die Orginal-Datei in der Regel nicht verändert wird, sondern eben ein Datenstrom erzeugt wird, der die Veränderungen enthält. Dieser Datenstrom kann natürlich dann mit Hilfe der Umleitungssymbole > in eine Datei umgeleitet werden oder über eine Pipe (|) zur Weiterverarbeitung an andere Programme weitergegeben werden.

Ein sed-Befehl beginnt mit einer optionalen Adresse oder einem Adressbereich. Dem folgt der Befehl, meist in Form eines Buchstabens und eventuelle Parameter des Befehls. Wird die Adresse weggelassen, so gilt der Befehl für jede Zeile.

Adressangaben

Adressen werden in verschiedenen Formen angegeben. Die wichtigsten sind: Zahl Eine Zahl meint die entsprechende Zeile. Die Adressangabe 12 meint also Zeile 12 des Eingabedatenstroms. $ Das Dollarzeichen meint die letzte Zeile des Eingabedatenstroms. Zahl1,Zahl2 Zwei durch Kommas getrennte Zahlen beschreiben einen Adressbereich. Die Angabe 2,14 meint also die Zeilen 2 bis 14. Oft gebraucht wird auch hier das Dollarzeichen als zweite Zahl, was also bedeutet „bis zum Ende des Datenstroms“. Die Angabe 22,$ meint also alles von Zeile 22 bis zur letzten Zeile. Zahl1~Zahl2 Der Befeh wird zuerst in der Zeile begonnen, die durch die erste Zahl angegeben wurde. Die zweite Zahl ist eine Schrittgröße, die bestimmt, welche weiteren Zeilen gemeint sind. Die Angabe 13~2 bedeutet also die Zeilen 13, 15, 17, 19 usw. /regexp/ Meint jede Zeile, die auf den regulären Ausdruck regexp zutrifft.

Wenn keine Adressangabe gemacht wird, so wird 1,$ angenommen, also jede Zeile des Datenstroms.

Befehle eingeben

Es gibt einige verschiedene Befehle für sed. Die Befehle werden entweder direkt auf der Kommandozeile eingegeben oder in eine separate Datei geschrieben, die dann auf der Kommandozeile angegeben wird. Die beiden Aufrufformen sind:

  sed -e Befehl

oder

  sed -f Datei

Einfache Befehle werden gerne direkt eingegeben, komplexere sollten schon der Übersichtlichkeit halber in einer Datei formuliert werden.

Wenn Befehle direkt eingegeben werden sollen, dann empfielt es sich, die Befehlszeile durch Hochkommas zu klammern, damit enthaltene Trennzeichen nicht von der Shell mißinterpretiert werden.

Wollen wir z.B. aus einem Datenstrom die 10. Zeile löschen, dann benützen wir die folgende Befehlszeile:

  ... | sed -e '10d'

Der Befehl zum Löschen ist das d (delete). Die 10 ist die Adressangabe für die 10. Zeile. 10d bedeutet also: Lösche die 10. Zeile.

Wollen wir einen ganzen Bereich löschen, sagen wir mal Zeile 7 bis 12, so geben wir eben eine Bereichsadresse an:

  ... | sed -e '7,12d'

Wollen wir aber mehrere unterschiedliche Zeilen löschen, so müssen wir entsprechend mehrere Zeilenangaben machen. sed-Befehle werden durch Zeilentrenner voneinander getrennt. Also schreiben wir:

  ... | sed -e '7d
  12d'

Das würde die Zeilen 7 und 12 löschen. Beachten Sie, dass durch die Verwendung der Hochkommas der Zeilentrenner nicht die Befehlszeile abschließt. Alternativ dazu hätten wir auch einfach zweimal die -e Option benutzen können:

  ... | sed -e '7d' -e '12d'

Irgendwann wird das unübersichtlich. Leichter wird das, wenn wir unsere Befehle in eine Datei schreiben, und diese Datei dann sed als Parameter mitgeben. Nehmen wir an, wir schreiben die folgenden Zeilen in die Datei kommandos.txt:

  7,12d
  23d
  45d

und rufen sed jetzt folgendermaßen auf:

  ... | sed -f kommandos.txt

Dann werden – erwartungsgemäß – die Zeilen 7 bis 12, 23 und 45 gelöscht.

Bitte beachten Sie, dass diese Zeilen – und alles andere, was wir mit sed machen – nicht in der Orginaldatei gelöscht werden. Nur die Ausgabe von sed enthält die gelöschten Zeilen nicht mehr.

Befehlsübersicht

Bei den Befehlen unterscheiden wir zwischen denen, die zusammen mit keiner-bis-einer Adresse verwendet werden und denen, die auf einen Adressbereich anwendbar sind.

Kommandos für keine-bis-eine Adresse

a \
einzufügender Text    
Text anhängen (append) Jeder im Text vorkommende Zeilentrenner muß durch einen Backslash „entwertet“ werden. Der Text wird nach der angegebenen Zeile eingefügt.
i \
einzufügender Text    
Text einfügen (insert) Jeder im Text vorkommende Zeilentrenner muß durch einen Backslash „entwertet“ werden. Der Text wird vor der angegebenen Zeile eingefügt.
r Dateiname    Der in der genannten Datei stehende Text wird nach der genannten Zeile angehängt.

Kommandos für keine-bis-mehrere Adressen

c \
einzufügender Text    
Der Text wird anstelle des genannten Zeilenbereichs eingefügt.
dDie genannte(n) Zeile(n) werden gelöscht
h HKopiert/Hängt den genannten Bereich in einen Zwischenpuffer an
g GKopiert/Hängt den Zwischenspeicher an den genannten Bereich an
xTauscht den Zwischenspeicher mit dem genannten Bereich
s/Suchbegriff/Ersatz/Sucht den Suchbegriff (auch reguläre Ausdrücke) und ersetzt ihn durch den angegebenen Ersatz. Der Ersatzbegriff kann das Sonderzeichen & enthalten, um den Bereich des durchsuchten Bereichs zu adressieren, der auf das Muster gepasst hatte und die Spezial-Sequenzen \1 bis \9, die die entsprechenden geklammerten Untermuster des Suchbegriffs referenzieren.
y/Quelle/Ziel/Ersetzt die einzelnen Zeichen aus Quelle durch die korrospondierenden Zeichen aus Ziel.
pGibt den genannten Bereich aus. Normalerweise gibt sed alles aus, es sei denn, das Programm wird mit der Option -n aufgerufen. Dann werden nur die Zeilen ausgegeben, die durch das p-Kommando betroffen sind.