Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
Shell-Programmierung von Jürgen Wolf
Einführung, Praxis, Referenz
Buch: Shell-Programmierung

Shell-Programmierung
782 S., mit CD, 44,90 Euro
Rheinwerk Computing
ISBN 3-89842-683-1
gp Kapitel 12 Der Stream-Editor sed
  gp 12.1 Funktions- und Anwendungsweise von sed
    gp 12.1.1 Wohin mit der Ausgabe?
  gp 12.2 Der sed-Befehl
  gp 12.3 Adressen
  gp 12.4 Kommandos, Substitutionsflags und Optionen von sed
    gp 12.4.1 Das a-Kommando – Zeile(n) anfügen
    gp 12.4.2 Das c-Kommando – Zeilen ersetzen
    gp 12.4.3 Das d-Kommando – Zeilen löschen
    gp 12.4.4 Die Kommandos h, H, g, G und x – Arbeiten mit den Puffern
    gp 12.4.5 Das Kommando i – Einfügen von Zeilen
    gp 12.4.6 Das p-Kommando – Patternspace ausgeben
    gp 12.4.7 Das Kommando q – Beenden
    gp 12.4.8 Die Kommandos r und w
    gp 12.4.9 Das Kommando s – substitute
    gp 12.4.10 Das Kommando y
  gp 12.5 sed-Scripts


Rheinwerk Computing

12.4 Kommandos, Substitutionsflags und Optionen von sedowntop

In den obigen Beispielen hatten Sie bisher immer die Option –n und das Kommando p verwendet. sed bietet neben p eine interessante Fülle von Kommandos an. Bevor Sie die einzelnen Kommandos und Optionen in der Praxis einsetzen, folgen hierzu die Tabellen 12.1 bis 12.3, welche die Optionen, Kommandos und so genannten Substitutionsflags zusammenfassen.

Zuerst die wichtigsten Kommandos von sed:


Tabelle 12.1   Gängige Basiskommandos von sed

Kommando Bedeutung
a (für append) Fügt eine oder mehrere Zeilen an die selektierte Zeile an.
c (für change) Ersetzt die selektierte Zeile durch eine oder mehrere neue.
d (für delete) Löscht Zeile(n).
g (für get »buffer«) Kopiert den Inhalt des temporären Puffers (Holdspace) in den Arbeitspuffer (Patternspace).
G (für GetNewline) Fügt den Inhalt des temporären Puffers (Holdspace) an den Arbeitspuffer (Patternspace) an.
h (für hold »buffer«) Gegenstück zu g; kopiert den Inhalt des Arbeitspuffers (Patternspace) in den temporären Puffer (Holdspace).
H (für HoldNewline) Gegenstück zu G; fügt den Inhalt des Arbeitspuffers (Patternspace) an den temporären Puffer (Holdspace) an.
i (für insert) Fügt eine neue Zeile vor der selektierten Zeile ein.
l (für listing) Zeigt nicht druckbare Zeichen an.
n (für next) Verwendet das nächste Kommando statt des aktuellen auf die nächste Zeile an.
p (für print) Gibt die Zeilen aus.
q (für quit) Beendet sed.
r (für read) Datei integrieren; liest Zeilen aus einer Datei ein.
s (für substitute) Ersetzen einer Zeichenfolge durch eine andere.
x (für Xchange) Vertauschen des temporären Puffers (Holdspace) mit dem Arbeitspuffer (Patternspace).
y (für yank) Zeichen aus einer Liste ersetzen; Ersetzen eines Zeichens durch ein anderes.
w (für write) Schreibt Zeilen in eine Datei.
! Negation; wendet die Kommandos auf Zeilen an, die nicht zutreffen.

Bei Verwendung einer Substitution mittels s/.../.../ können noch zusätzliche Flags (Substitutionsflags) angegeben werden, die am Ende des Befehls notiert werden. Bspw. findet mit s/.../.../g eine globale Ersetzung statt, das heißt, es werden alle Vorkommen eines Musters in einer Zeile ersetzt. Ohne g würde nur das erste Vorkommen ersetzt. Hier einige dieser Flags und deren Bedeutung:


Tabelle 12.2   Einige Substitutionsflags

Flag Bedeutung
g Globale Ersetzung (aller Vorkommen eines Musters in der Zeile).
p Ausgabe der Zeile.
w Tauscht den Inhalt des Zwischenspeichers mit der aktuell selektierten Zeile aus.

Die Schalter-Optionen, die Sie mit sed verwenden können, lauten:


Tabelle 12.3   Gängige Schalter-Optionen für sed

Option Bedeutung
–n Schaltet »Default Output« aus; mit dem Default Output ist die Ausgabe des Puffers (Patternspace) gemeint.
–e Mehrere Befehle nacheinander ausführen; man gibt praktisch ein Script bzw. die Kommandos direkt in der Kommandozeile ein.
–f Die sed-Befehle in einem Script (sed-Script) zusammenfassen und dieses Script mittels –f übergeben; praktisch wie die Option –e, nur dass hier anstatt des Scripts bzw. Kommandos in der Kommandozeile der Name eines Scriptfiles angegeben wird.


Hinweis   Die meisten sed-Versionen (GNU-sed, BSD-sed, FreeBSD-sed und ssed) bieten neben diesen Optionen noch einige weitere an, dessen Bedeutung Sie bei Bedarf der Manual-Page von sed entnehmen können.


Wie grep versteht auch sed eine Menge regulärer Ausdrücke. Auch hier bieten die unterschiedlichen sed-Versionen die ein oder andere Erweiterung an. Allerdings begnügen wir uns hier wieder mit den Basic-Ausdrücken. Die regulären Ausdrücke, die sed versteht, finden Sie in Tabelle 12.4 aufgelistet:


Tabelle 12.4   Grundlegende reguläre Ausdrücke, die sed versteht

Ausdruck Bedeutung Beispiel Erklärung
^ Anfang einer Zeile /^wort/ Behandelt alle Zeilen, die mit der Zeichenfolge wort beginnen.
$ Ende einer Zeile /wort$/ Behandelt alle Zeilen, die mit der Zeichenfolge wort enden.
. Ein Zeichen /w.rt/ Behandelt alle Zeilen mit den Zeichenfolgen wort, wert, wirt, wart etc. (Ausname ist das Newline-Zeichen).
* keine, eine oder mehrere Wiederholungen des vorhergehenden Zeichens (oder Gruppe) /*wort/ Behandelt alle Zeilen, in denen vor wort kein, ein oder mehrere Zeichen stehen.
[] ein Zeichen aus der Menge /[Ww]ort/ Behandelt alle Zeilen mit der Zeichenfolge wort oder Wort.
[^] Kein Zeichen aus der Menge /[^Ww]ort/ Behandelt alle Zeilen die nicht die Zeichenfolge wort oder Wort enthalten.
\(...\) Speichern eines enthaltenen Musters S/\(wort\)a/\1b/ Die Zeichenfolge wort wird in \1 gespeichert. Diese Referenz auf das Muster wort verwenden Sie nun, um in der Zeichenfolge worta das Wort wortb zu ersetzen. Damit lassen sich bis zu 9 solcher Referenzen definieren, worauf Sie mit \1, \2 ... \9 zugreifen können.
& enthält das Suchmuster S/wort/Ant&en/ Das Ampersand-Zeichen repräsentiert den Suchstring. Im Beispiel wird jeder Suchstring wort durch das Wort Antworten ersetzt.
\< Wortanfang /\<wort/ Findet alle Zeilen mit einem Wort, das mit wort beginnt, also wortreich, wortarm, nicht aber Vorwort oder Nachwort.
\> Wortende /wort\>/ Findet alle Zeilen mit einem Wort, das mit wort endet, also Vorwort, Nachwort, nicht aber wortreich oder wortarm.
x\{m\} x\{m,\} x\{m,n\} m-fache Wiederholung des Zeichens x mindestens m-fache Wiederholung des Zeichens x mindestens m-, maximal n-fache Wiederholung des Zeichens x

Nachdem Sie jetzt eine Menge Theorie und viele Tabellen gesehen haben, folgt nun ein Praxisteil zu der Verwendung der einzelnen Kommandos von sed. Als Beispiel soll wieder die Datei mrolympia.dat verwendet werden:

you@host > cat mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Des Weiteren muss erwähnt werden, dass alle Beispiele auf dem Patternspace-Puffer ausgeführt werden. Somit bezieht sich die Änderung nur auf die Ausgabe auf dem Bildschirm (Standardausgabe). Sofern Sie hier gern eine bleibende Änderung vornehmen wollen (was in der Regel der Fall sein sollte), können Sie sich auf Abschnitt 12.1.1 beziehen. Die einfachste Lösung dürfte hier wohl die Verwendung des Umlenkungszeichens am Ende des sed-Befehls sein.


Rheinwerk Computing

12.4.1 Das a-Kommando – Zeile(n) anfügen  downtop

Die Syntax:

a\
neue Zeile
# oder in neueren sed-Versionen auch
a neue Zeile

Mit dem a-Kommando (append) können Sie eine neue Zeile hinter einer gefundenen Zeile einfügen. Bspw.:

you@host > sed '/2004/ a Jay Cutler 2005' mrolympia.dat
...
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Jay Cutler 2005

Sollte die Zeile länger werden, können Sie der Übersichtlichkeit zuliebe ein Backslash verwenden:

you@host > sed '/2004/ a\
> Prognosse für 2005: J.Cutler; R.Coleman; M.Rühl' mrolympia.dat
...
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Prognosse für 2005: J.Cutler; R.Coleman; M.Rühl'

Hinweis   Dass das Kommando a und die neue Zeile in derselben Zeile stehen, ist eine Erweiterung neuerer sed-Versionen. Ältere sed-Programme kennen häufig nur das a-Kommando gefolgt von einem Backslash und die neue Zeile dann in der nächsten Zeile. Dies sollten Sie wissen, falls Sie auf einem etwas betagteren Rechner mit sed arbeiten müssen.


Beachten Sie außerdem, dass jedes Whitespace nach dem a-Kommando hinter dem Backslash ebenfalls als ein Zeichen interpretiert und verwendet wird.


Rheinwerk Computing

12.4.2 Das c-Kommando – Zeilen ersetzen  downtop

Die Syntax:

c\
neuer Text
# oder in neueren sed-Versionen
c neuer Text

Wollen Sie eine gefundene Zeile komplett durch eine neue Zeile ersetzen, können Sie das c-Kommando (change) verwenden. Die Funktionsweise entspricht der des a-Kommandos.

you@host > sed '/\<Oliva\>/ c \
> Sergio Oliva Cuba 1967 1968 1969' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva Cuba 1967 1968 1969
...

Im Beispiel wurden alle Zeilen mit dem Vorkommen des Wortes »Oliva« durch die in der darauf folgenden Zeile vorgenommene Eingabe ersetzt. Hier wurde bspw. die Nationalität verändert. Dem c-Kommando muss wie beim a-Kommando ein Backslash und ein Newline-Zeichen folgen – obgleich auch hier die neueren sed-Versionen ohne Backslash und Newline-Zeichen auskommen.


Rheinwerk Computing

12.4.3 Das d-Kommando – Zeilen löschen  downtop

Zum Löschen von Zeilen wird das d-Kommando (delete) verwendet. Damit wird die entsprechende Adresse im Puffer gelöscht. Ein paar Beispiele.

Löscht die fünfte Zeile:

you@host > sed '5d' mrolympia.dat

Löscht ab der fünften bis zur neunten Zeile:

you@host > sed '5,9d' mrolympia.dat

Löscht alle Zeilen ab der fünften Zeile bis zum Ende der Datei:

you@host > sed '5,$d' mrolympia.dat

Löscht alle Zeilen, welche das Muster »USA« enthalten:

you@host > sed '/USA/d' mrolympia.dat

Löscht alle Zeilen, die nicht das Muster »USA« enthalten:

you@host > sed '/!USA/d' mrolympia.dat

Rheinwerk Computing

12.4.4 Die Kommandos h, H, g, G und x – Arbeiten mit den Puffern  downtop

Mit den Kommandos g (get), G (GetNewline), h (hold), H (HoldNewline) und x (Xchange) können Sie mit den Puffern (Patternspace und Holdspace) arbeiten.

Mit dem Kommando h können Sie den aktuellen Inhalt des Zwischenpuffers (Patternspace) in einen anderen Puffer (Holdspace) sichern. Mit H hängen Sie ein Newline-Zeichen an das Ende des Puffers, gefolgt vom Inhalt des Zwischenpuffers.

Mit g, dem Gegenstück zu h, ersetzen Sie die aktuelle Zeile des Zwischenpuffers durch den Inhalt des Puffers, den Sie zuvor mit h gesichert haben. Mit G hängen Sie ein Newline-Zeichen an das Ende des Zwischenpuffers, gefolgt vom Inhalt des Puffers.

Mit dem Kommando x hingegen tauschen Sie den Inhalt des Zwischenpuffers mit dem Inhalt des anderen Puffers aus.

Ein Beispiel:

you@host > sed -e '/Sergio/{h;d}' -e '$G' mrolympia.dat

Hierbei führen Sie zunächst eine Suche nach dem Muster »Sergio« in der Datei mrolympia.dat durch. Wird eine entsprechende Zeile gefunden, legen Sie diese in den Holdspace zum Zwischenspeichern (Kommando h). Im nächsten Schritt löschen Sie diese Zeile (Kommando d). Anschließend führen Sie (Option –e) das nächste Kommando aus. Hier hängen Sie praktisch die Zeile im Holdspace (G) mit einem beginnenden Newline-Zeichen an das Ende des Patternspace. Diese Zeile wird an das Ende angehängt ($-Zeichen). Wollen Sie diese Zeile bspw. in die fünfte Zeile platzieren, gehen Sie wie folgt vor:

you@host > sed -e '/Sergio/{h;d}' -e '5G' mrolympia.dat
Larry Scott USA 1965 1966
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Sergio Oliva USA 1967 1968 1969
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Bitte beachten Sie, dass hierbei die gelöschte Zeile beim Einfügen mit berechnet wird. Was passiert nun, wenn Sie die Zeile im Holdspace ohne Newline-Zeichen, wie dies mit g der Fall ist, im Patternspace einfügen? Folgendes:

you@host > sed -e '/Sergio/{h;d}' -e '5g' mrolympia.dat
Larry Scott USA 1965 1966
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Sergio Oliva USA 1967 1968 1969
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Hier wird praktisch gnadenlos eine Zeile (hier »Chris Dickerson«) überschrieben. Beachten Sie dies bitte bei der Verwendung von g und G bzw. h und H.

Noch ein Beispiel zum Kommando x:

you@host > sed -e '/Sergio/{h;d}' -e '/Dorian/x' \
> -e '$G' mrolympia.dat
Larry Scott USA 1965 1966
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Sergio Oliva USA 1967 1968 1969
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Jay Cutler 2005
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997

Hier suchen Sie zunächst nach dem Muster »Sergio«, legen dies in den Holdspace (Kommando h) und löschen daraufhin die Zeile im Patternspace (Kommando d). Jetzt suchen Sie nach dem Muster »Dorian« und tauschen den Inhalt des Patternspace (Zeile mit »Dorian«) mit dem Inhalt des Holdspace (Zeile »Sergio«). Jetzt befindet sich im Holdspace die Zeile mit »Dorian«, diese hängen Sie mit einem weiteren Befehl (Option –e) an das Ende des Patternspace.


Rheinwerk Computing

12.4.5 Das Kommando i – Einfügen von Zeilen  downtop

Die Syntax:

i\
text zum Einfügen
# oder bei neueren sed-Versionen
i text zum Einfügen

Bei diesem Kommando gilt all das, was schon zum Kommando a gesagt wurde. Damit können Sie eine neue Zeile vor der gefundenen Zeile einfügen.

you@host > sed '/Franco/ i \
> ---Zeile---' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
---Zeile---
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
...

Rheinwerk Computing

12.4.6 Das p-Kommando – Patternspace ausgeben  downtop

Dieses Kommando wurde schon zur Genüge verwendet. Mit p geben Sie den Patternspace aus. Wollen Sie bspw. einfach eine komplette Datei ausgeben lassen, können Sie folgendermaßen vorgehen:

you@host > sed -n 'p' mrolympia.dat

Die Option –n ist hierbei nötig, da sonst neben dem Patternspace-Puffer auch noch der Default Output mit ausgegeben würde und Sie somit eine doppelte Ausgabe hätten. Mit –n schalten Sie den Default Output aus. Dies wird gern vergessen und führt zu Fehlern. Wollen Sie bspw. die letzte Zeile in einer Datei ausgeben lassen und vergessen dabei, den Default Output abzuschalten, bekommen Sie folgende Ausgabe zurück:

you@host > sed '$p' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Hier wird trotzdem die komplette Datei ausgegeben, da der Default Output weiterhin über den Bildschirm rauscht. Die letzte Zeile hingegen ist doppelt vorhanden, weil hier zum einen der Default Output seine Arbeit gemacht hat und zum anderen das p-Kommando auch noch einmal die letzte Zeile mit ausgibt. Richtig wäre hier also:

you@host > sed -n '$p' mrolympia.dat
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Noch einige typische Beispiele mit dem p-Kommando:

you@host > sed -n '4p' mrolympia.dat
Franco Columbu Argentinien 1976 1981

Hier wurde die vierte Zeile ausgegeben.

you@host > sed -n '4,6p' mrolympia.dat
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983

Hiermit werden die Zeilen 4 bis 6 ausgegeben.

you@host > sed -n '/USA/p' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Chris Dickerson USA 1982
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Hierbei werden alle Zeilen mit der Textfolge »USA« ausgegeben.


Rheinwerk Computing

12.4.7 Das Kommando q – Beenden  downtop

Mit dem Kommando q können Sie das laufende sed-Script durch eine Verzweigung zum Scriptende beenden. Vorher wird aber noch der Patternspace ausgegeben. Ein einfaches Beispiel:

you@host > sed -n '/USA/{p;q}' mrolympia.dat
Larry Scott USA 1965 1966

Hier wird der sed-Befehl nach dem ersten gefundenen Muster »USA« beendet. Zuvor wird noch der Inhalt des Patternspace ausgegeben.


Rheinwerk Computing

12.4.8 Die Kommandos r und w  downtop

Mit dem Kommando r können Sie aus einer Datei einen Text einschieben. In den seltensten Fällen werden Sie einen Text in nur einer Datei einfügen wollen. Hierzu sei folgende einfache Textdatei gegeben:

you@host > cat header.txt
---------------------------------
Vorname Name Nationalität Jahr(e)
---------------------------------

Der Inhalt dieser Datei soll jetzt mit dem Kommando r in die letzte Zeile eingefügt werden:

you@host > sed '$r header.txt' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
...
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Jay Cutler 2005
---------------------------------
Vorname Name Nationalität Jahr(e)
---------------------------------

Natürlich können Sie auch die Zeilennummer oder ein Muster als Adresse für das Einfügen verwenden:

you@host > sed -e '/Arnold/r header.txt' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
---------------------------------
Vorname Name Nationalität Jahr(e)
---------------------------------
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
...

Ebenso können Sie auch mehr als nur eine Datei mithilfe der –e-Option aus einer Datei einlesen lassen und in die entsprechenden Zeilen einfügen.

you@host > sed -e '3r file1.dat' -e '7r file2.dat' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
----------Ich bin file1------------
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
----------Ich bin file2------------
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Das entsprechende Gegenstück zum Kommando r erhalten Sie mit dem Kommando w, mit dem Sie das Ergebnis von sed in einer Datei speichern können:

you@host > sed -n '/USA/w USA.dat' mrolympia.dat
you@host > cat USA.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Chris Dickerson USA 1982
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004

Rheinwerk Computing

12.4.9 Das Kommando s – substitute  downtop

Bei dem s-Kommando handelt sich wohl um das meistverwendete Kommando in sed und es ist auch einer der Hauptgründe, sed überhaupt zu verwenden. Die Syntax:

sed -e 's/altes_Muster/neues_Muster/flag' datei
sed -e 's?altes_Muster?neues_Muster?flag' datei

Damit können Sie das Muster »altes_Muster« (im Patternspace) von datei durch »neues_Muster« ersetzen. Als Trennzeichen (hier einmal mit / und ?) können Sie praktisch jedes beliebige Zeichen verwenden (außer Backslash und Newline-Zeichen), es darf nur nicht Bestandteil des Musters sein.

In der Grundform, ohne Angabe von »flag«, ersetzt das Kommando s nur das erste Vorkommen eines Musters pro Zeile. Somit können Sie mit der Angabe von »flag« auch das Verhalten von s verändern. Am häufigsten verwendet wird wohl das Flag g, mit dem alle Vorkommen eines Musters in einer Zeile nacheinander ersetzt werden – also eine globale Ersetzung. Mit dem Flag q wird nach der letzten Ersetzung der Patternspace ausgegeben, mit dem Flag w können Sie den Patternspace in die angegebene Datei schreiben. Allerdings muss diese Option die letzte im Flag sein, da der Dateiname bis zum Ende der Zeile geht. Selbstverständlich werden gerade zu diesem Kommando jetzt massenhaft Beispiele folgen.

you@host > sed 's/USA/Amerika/g' mrolympia.dat
Larry Scott Amerika 1965 1966
Sergio Oliva Amerika 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson Amerika 1982
Samir Bannout Libanon 1983
Lee Haney Amerika 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman Amerika 1998 1999 2000 2001 2002 2003 2004

Hier wurden global alle Zeichenfolgen »USA« durch »Amerika« ersetzt. Natürlich können Sie hierbei auch einzelnen Zeilen mithilfe einer Adresse verändern:

you@host > sed '/Oliva/ s/USA/Cuba/' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva Cuba 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
...

Hier wurde nur die Zeile ersetzt (»USA« durch »Cuba«), in der sich die Textfolge »Olivia« befindet. Wollen Sie nicht, dass hier die komplette Datei ausgegeben wird, sondern nur die Zeile(n), die ersetzt wurde(n), müssen Sie das Flag p (mit der Option –n) verwenden:

you@host > sed -n '/Oliva/ s/USA/Cuba/p' mrolympia.dat
Sergio Oliva Cuba 1967 1968 1969

Das nächste Beispiel:

you@host > sed 's/[12][90]/-/' mrolympia.dat
Larry Scott USA –65 1966
Sergio Oliva USA –67 1968 1969
Arnold Schwarzenegger Österreich –70 1971 1972 1973 1974 1975 1980
Franco Columbu Argentinien –76 1981
Chris Dickerson USA –82
Samir Bannout Libanon –83
Lee Haney USA –84 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien –92 1993 1994 1995 1996 1997
Ronnie Coleman USA –98 1999 2000 2001 2002 2003 2004

Hier konnten Sie zum ersten Mal den Einfluss des g-Flags erkennen. Es sollten wohl alle Zeichenfolgen »19« und »20« durch ein Minuszeichen ersetzt werden. Dasselbe nochmals mit dem Flag g:

you@host > sed 's/[12][90]/-/g' mrolympia.dat
Larry Scott USA –65 –66
Sergio Oliva USA –67 –68 –69
Arnold Schwarzenegger Österreich –70 –71 –72 –73 –74 –75 –80
Franco Columbu Argentinien –76 –81
Chris Dickerson USA –82
Samir Bannout Libanon –83
Lee Haney USA –84 –85 –86 –87 –88 –89 –90 –91
Dorian Yates Grossbritannien –92 –93 –94 –95 –96 –97
Ronnie Coleman USA –98 –99 –00 –01 –02 –03 –04

Hier werden auch die Zeichenfolgen »10«, »20« und »29« beachtet. Wollen Sie statt einer Ersetzung eine Ergänzung machen, können Sie das Ampersand-Zeichen (&) beim Ersetzungsstring verwenden:

you@host > sed -n 's/Franco Columbu/Dr. &/p' mrolympia.dat
Dr. Franco Columbu Argentinien 1976 1981

Hier wurde der Suchstring »Franco Columbu« exakt an der Position des »Ampersand-Zeichens« beim Ersetzungsstring verwendet und ein Titel davor gesetzt. Sofern Sie etwas Derartiges global durchführen müssen und nur die ersetzten Pattern ausgeben wollen, können Sie auch die Flags g und p gleichzeitig verwenden:

you@host > sed -n 's/USA/& (Amerika)/gp' mrolympia.dat
Larry Scott USA (Amerika) 1965 1966
Sergio Oliva USA (Amerika) 1967 1968 1969
Chris Dickerson USA (Amerika) 1982
Lee Haney USA (Amerika) 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA (Amerika) 1998 1999 2000 2001 2002 2003 2004

Mit der Option –e können Sie auch mehrere Ersetzungen auf einmal durchführen lassen:

you@host > sed -e 's/USA/& (Amerika)/g' \
> -e 's/[12][90]/-/g'  mrolympia.dat
Larry Scott USA (Amerika) –65 –66
Sergio Oliva USA (Amerika) –67 –68 –69
Arnold Schwarzenegger Österreich –70 –71 –72 –73 –74 –75 –80
Franco Columbu Argentinien –76 –81
Chris Dickerson USA (Amerika) –82
Samir Bannout Libanon –83
Lee Haney USA (Amerika) –84 –85 –86 –87 –88 –89 –90 –91
Dorian Yates Grossbritannien –92 –93 –94 –95 –96 –97
Ronnie Coleman USA (Amerika) –98 –99 –00 –01 –02 –03 –04

Gleiches können Sie übrigens auch mit einer Referenz wie folgt machen:

you@host > sed -n 's/\(USA\)/\1 (Amerika)/gp' mrolympia.dat
Larry Scott USA (Amerika) 1965 1966
Sergio Oliva USA (Amerika) 1967 1968 1969
Chris Dickerson USA (Amerika) 1982
Lee Haney USA (Amerika) 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA (Amerika) 1998 1999 2000 2001 2002 2003 2004

Hier wird \1 als Referenz auf »USA« beim Ersetzungsstring verwendet.

Betrachten Sie mal folgendes Beispiel:

you@host > sed -n 's/\([12][90]\)\(..\)/\/\1\2\//gp' \
> mrolympia.dat

Beim Anblick dieser Zeile fällt es schon schwer, den Überblick zu behalten. Hier sollen alle Jahreszeiten zwischen zwei Schrägstrichen gesetzt werden (/2000/, /2001/ etc). Bei der Verwendung solcher Zeichen-Orgien empfiehlt es sich, häufiger mal ein anderes Trennzeichen zu verwenden:

you@host > sed -n 's#\([12][90]\)\(..\)#\/\1\2\/#gp' \
> mrolympia.dat

Jetzt kann man wenigstens leichter zwischen dem Such- und Ersetzungsstring unterscheiden.

Man könnte noch extremere Auswüchse zum Suchen und Ersetzen mit sed schreiben, doch erscheint es mir an dieser Stelle wichtiger, ein Problem mit den regulären Ausdrücken zu erwähnen, das mich zur Weißglut beim Schreiben eines Artikels zur Verwendung von sed in Verbindung mit HTML-Seiten gebracht hat. Erst ein Artikel im Internet von Thomas Pircher hat dann für klare Verhältnisse gesorgt. Das Problem: Ein regulärer Ausdruck sucht sich immer den längsten passenden String. Bspw. folgende Textfolge in einem HTML-Dokument:

Dies ist ein <strong>verflixte</strong> Stelle in einem <strong>verflixten</strong> 
HTML-Dokument.

Ich wollte alle HTML-Tags aus dem Dokument entfernen, um so eine normale Textdatei daraus zu machen. Mit folgendem Konstrukt wollte ich dies realisieren:

sed -e 's/<.*>//g' index.html

Mit folgendem Ergebnis:

Das ist ein HTML-Dokument.

Leider war mir nicht (mehr) klar, dass .* so gefräßig ist (eigentlich war es mir aus Perl bekannt) und die längste Zeichenfolge sucht, also von

<strong>verflixte</strong> Stelle in einem <strong>verflixten
</strong>

haben will. Um aber nur die Zeichen bis zum ersten Auftreten des Zeichens > zu löschen, muss man mit folgender Bereichsangabe arbeiten:

sed -e 's/<[^>]*>//g' index.html

Hieran können Sie erkennen, dass die Verwendung regulärer Ausdrücke recht kompliziert werden kann und man häufig um eine intensivere Beschäftigung mit ihnen nicht herumkommt. Gerade, wenn Sie reguläre Ausdrücke beim Suchen und Ersetzen mehrerer Dateien verwenden, sollten Sie sich sicher sein, was Sie tun und gegebenenfalls einen Probelauf vornehmen bzw. ein Backup zur Hand haben. Zum Glück – und vielleicht auch deswegen – wurde sed so konzipiert, dass die Manipulation erst mal nicht an der Originaldatei gemacht wird.

Manch einer mag jetzt fragen, wie man Dateien vom DOS-Format ins UNIX-Format und umgekehrt konvertieren kann. Mit sed ist dies leichter als man denkt. Man gehe davon aus, dass eine DOS-Zeile mit CR und LF endet. Ich habe das Beispiel der sed-FAQ von Eric Pement entnommen:

# 3. Under UNIX: convert DOS newlines (CR/LF) to Unix format
sed 's/.$//' file    # assumes that all lines end with CR/LF
sed 's/^M$// file    # in bash/tcsh, press Ctrl-V then Ctrl-M

Allerdings stellt sich die Frage, ob man hierbei nicht auf die Tools dos2unix bzw. unix2dos zurückgreifen will. Beim vim können Sie auch mittels set (set fileformat=dos oder set fileformat=unix) das Dateiformat angeben.


Hinweis   Man könnte fragen, warum in diesem Beispiel zur Konvertierung von DOS-Zeilen in UNIX-Zeilen nicht folgendes Konstrukt verwendet wurde:

's/\r\n/\n/g'

Weil es so nicht überall (bspw. Debian) zu funktionieren scheint.



Rheinwerk Computing

12.4.10 Das Kommando y  toptop

Ein weiteres Kommando, das neben dem Kommando s gern verwendet wird, ist y (yank), mit dem Sie eine Ersetzung von Zeichen aus einer Liste vornehmen können. Die Syntax:

y/Quellzeichen/Zielzeichen/

Hiermit werden alle Zeichen in »Quellzeichen« in die entsprechenden Zeichen in »Zielzeichen« umgewandelt. Ist eine der Listen leer oder unterschiedlich lang, wird sed mit einem Fehler beendet. Natürlich können Sie auch (wie schon beim Kommando s) als Trenner ein anderes Zeichen als / verwenden. Bspw. können Sie mit folgendem sed-Befehl eine Datei nach der »rot-13«-Methode verschlüsseln (hier nur auf die Kleinbuchstaben beschränkt):

you@host > cp mrolympia.dat mrolympia.bak
you@host > sed –e \
> 'y/abcdefghijklmnopqrstuvwxyz/nopqrstuvwxyzabcdefghijklm/' \
> mrolympia.bak > mrolympia.dat
you@host > cat mrolympia.dat
Lneel Spbgg USA 1965 1966
Sretvb Oyvin USA 1967 1968 1969
Aeabyq Spujnemrarttre Öfgrervpu 1970 1971 1972 1973 1974 1975
Fenapb Cbyhzoh Aetragvavra 1976 1981
...

Hiermit werden alle (Klein-)Buchstaben um 13 Zeichen verschoben, aus »a« wird »n«, aus »b« wird »o«, aus »c« wird »p« usw. Wollen Sie das Ganze wieder rückgängig machen, brauchen Sie »Quellzeichen« und »Zielzeichen« aus dem Beispiel nur auszutauschen:

you@host > cp mrolympia.dat mrolympia.bak
you@host > sed –e \
> 'y/nopqrstuvwxyzabcdefghijklm/abcdefghijklmnopqrstuvwxyz/' \
> mrolympia.bak > mrolympia.dat
you@host > cat mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
...


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 << zurück
  
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Shell-Programmierung
Shell-Programmierung
bestellen
 Buchtipps
Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-Programmierung


Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2005
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern