sed

Aus Mikiwiki
Version vom 11. Dezember 2024, 11:28 Uhr von Michi (Diskussion | Beiträge) (→‎Option "s")
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Der Shell-Befehl sed (stream editor) ist ein Zeileneditor und arbeitet im Gegensatz zu Texteditoren wie vi nicht interaktiv. Stattdessen wird vorher auf der Befehlszeile bestimmt, welche Textbereiche zu löschen, zu ändern oder einzufügen sind. sed bearbeitet jede Zeile mit den angeführten Befehlen und schreibt sie in einen Puffer, dessen Inhalt zuletzt - falls nicht anders definiert - auf der Standardausgabe (stdout) erscheint.

Der Befehl N liest eine weitere Zeile in den "pattern space", ohne die aktuelle Zeile zu entfernen. Andere Befehle beenden sed, bevor die ganze Quelldatei bearbeitet wurde. Zudem gibt es neben dem "pattern space" auch den "hold space".

Syntax

Normalerweise erhält sed die zu verarbeitenden Texte über die Standardeingabe (stdin). Dabei können eine oder mehrere Dateien angegeben werden. Damit die Shell den Befehl nicht auswertet, wird er in einfache Hochkommas gesetzt.

sed [Optionen] 'Befehle' Dateien

Die Angabe, welche Zeilen oder Dateibereiche zu bearbeiten sind, wird als "Adresse" bezeichnet.

Die Befehle können auch in eine Skriptdatei geschrieben werden.

sed -f scriptfile sourcefile > targetfile

Zu fluchtende Zeichen

sed verwendet grundlegende reguläre Ausdrücke - um die Zeichen $ . * [ \ ^ als gewöhnliche Zeichen zu behandeln, müssen diese mit dem rückwärtsgerichteten Schrägstrich gefluchtet werden. Buchstaben, Zahlen und die Zeichen ( ) { } + ? | müssen nicht gefluchtet werden.

In Wirklichkeit ist das alles aber viel komplizierter... siehe

Optionen

Option Beschreibung
p Ausgabe der entsprechenden Zeilen auf den Bildschirm.
d Löschen des angegebenen Bereichs.
s Ersetzung der angegebenen Zeichenkette.
a Einfügen von Text hinter den adressierten Zeilen (beim Einsatz in Skripten).
i Einfügen von Text vor den adressierten Zeilen (beim Einsatz in Skripten).
c Ersetzen von Zeilen oder Zeilenbereichen (beim Einsatz in Skripten).
r Lesen des Inhalts einer Datei und Setzen des Inhalts hinter die entsprechende Adresse.
w Schreiben der adressierten Zeilen oder Bereiche in eine neue Datei.
Beispiel Beschreibung
s/CA/California/g ändert alle "CA" der Quelldatei in "California". Da keine Adresse angegeben ist, werden alle Zeilen bearbeitet.
s/*//g ersetzt einen oder mehrere Leerschläge hintereinander durch einen einzelnen Leerschlag.
/Sebastopol/s/CA/California/g ändert alle "CA" der Quelldatei in "California", falls die jeweilige Zeile "Sebastopol" enthält. Da hier eine Adresse vorhanden ist (Sebastopol), werden nur die der Adresse entsprechenden Zeilen bearbeitet.
d löscht alle Zeilen
  • 1d löscht die erste Zeile
  • $d löscht die letzte Zeile
  • /^$/d löscht leere Zeilen
  • /^\.TS/,/^\.TE/d löscht alle Zeilen, auf die das erste Muster passt bis und mit der ersten Zeile, auf die das zweite Muster passt
/^\.TS/,/^\.TE/d{
/^$/d
}
löscht leere Zeilen nur in dem von den beiden Mustern vorgegebenen Bereich. Zwischen den geschweiften Klammern (die je auf eigenen Zeilen wie im Beispiel stehen müssen) können auch mehrere Befehle vorkommen.

Verwendung

Option "p"

Ausgabe des Inhalts der Datei "file".

$ sed '' file

Ausgabe des Inhalts der Datei "file", wobei die dritte Zeile zweimal angezeigt wird.

$ sed '3p' file

Ausgabe nur der dritten Zeile der Datei "file".

$ sed -n '3p' file

Option "d"

Löschen der ersten Zeile der Datei "file".

$ sed '1d' file

Löschen der zweiten bis vierten Zeile der Datei "file".

$ sed '2,4d' file

Löschen jeder dritten Zeile (ausgehend von der ersten) der Datei "file".

$ sed '1~3d' file

Löschen von Zeile 5 und aller folgenden bis zum Dateiende der Datei "file".

$ sed '5,$d' file

Löschen aller Zeilen, die mit einem Rautenzeichen beginnen (z. B. zum besseren Betrachten von Konfigurationsdateien). Dabei werden allerdings auch die Leerzeilen mit ausgegeben.

$ sed '/^#/d' /etc/hosts

Ausgabe aller Zeilen, die mit einem Zeichen beginnen das kein Rautenzeichen ist. Leerzeilen werden also nicht ausgegeben.

$ sed -n '/^ [^#].*/p' /etc/hosts

Option "s"

Mit der Option "s" werden Zeichenketten ersetzt. Nach dem Befehl folgt ein Trennzeichen, das Suchmuster, ein weiteres Trennzeichen, die neu einzufügende Zeichenkette und ein abschliessendes Trennzeichen. Als Trennzeichen kann ein beliebiges Zeichen verwendet werden, es darf aber nicht im Suchmuster vorkommen.

Ersetzen der jeweils ersten Zeichenfolge "abc" durch "xyz" in jeder Zeile der Datei "file".

$ sed 's/abc/xyz/' file

Ersetzen aller Zeichenfolgen "abc" durch "xyz" in jeder Zeile der Datei "file".

$ sed 's/abc/xyz/g' file

Ersetzen aller Zeichenfolgen "abc" durch "xyz" in Zeile 3 der Datei "file".

$ sed '3s/abc/xyz/g' file

Ersetzen aller Zeichenfolgen "http://abc.org/" durch "http://xyz.org/" in jeder Zeile der Datei "file". Da der Schrägstrich hier im Suchmuster vorkommt, wird als Trenner das Rautenzeichen verwendet.

$ sed 's#http://abc.org/#http://xyz.org/#g' file

Ersetzen von Zeilenumbrücken ("\n") in der Datei "file" durch die Zeichenfolge "ABCD".

$ sed ':M;N;$!bM;s#\n#ABCD#g' file

Ersetzen des Zeichens "`" in der Datei "file" durch "'" (Apostroph).

$ sed 's/`/'\''/g' file

Ersetzen des zweiten Vorkommens des Zeichens ";" durch einen Bindestrich.

$ echo "XXX ; YYY ; ZZZ" | sed 's/;/-/2'
XXX ; YYY - ZZZ

Umwandlung des ersten Buchstabens jeder Zeile der Datei "file" in einen Grossbuchstaben.

$ sed 's/^\(\<.\)/\U\1/g' file

Umwandlung des ersten Buchstabens jeder Zeile der Datei "file" in einen Kleinbuchstaben.

$ sed 's/^\(\<.\)/\L\1/g' file

Umwandlung des ersten Buchstabens nach der ersten vorkommenden Klammer "(" jeder Zeile in einen Grossbuchstaben.

$ echo "abc(Zuz)hjh" | sed 's/(\(.\)/(\U\1/'
abc(Zuz)hjh

Entfernen eckiger Klammern.

$ echo "[Text]" | sed 's/\(\[\|\]\)//g'
Text

Entfernen der Zeichenfolgen "EAN: " oder "UPC: " am Zeilenbeginn.

$ echo "EAN: 9789953897035" | sed -e '${s/^EAN: \|^UPC: //}'
9789953897035

Mehrere Befehle

Löschen von Zeile 5 und aller folgenden bis zum Dateiende der Datei "file". Im Rest der Datei wird die Zeichenfolge "KDE" durch "Gnome" ersetzt.

$ sed -e '5,$d' -e 's/KDE/Gnome/g' file
oder
$ sed '{5,$d;'s/KDE/Gnome/g' file

Lesen und Schreiben

Einfügen der Datei "infile" nach der dritten Zeile der Datei "file".

$ sed '3r infile' file

Schreiben der Zeilen 25 bis 35 der Datei "file" in die neue Datei "outfile".

$ sed '25,35w outfile' file

sed-Skript

Mehrere sed-Befehle können auch in eine Skript-Datei geschrieben werden, die dann mit der Option "-f" auf die gewünschten Dateien angesetzt wird.

Löschen von Zeile 2 und Ergänzen des Texts "Nach der dritten Zeile" nach Zeile 3 der Datei "file". Für den Befehl "a" ist es wichtig, dass nach dem Befehl ("3a") ein umgekehrter Schrägstrich und Zeilenumbruch eingefügt wird. Der einzufügende Text steht dann in einer neuen Zeile. Handelt es sich um mehrere Zeilen, so muss jede (bis auf die letzte) mit einem umgekehrten Schrägstrich abgeschlossen werden.

$ more scriptfile
2d
3a\
Nach der dritten Zeile.\
Noch etwas.\
Und Schluss.
$ sed -f scriptfile file

Schreiben in eine Datei

sed verändert standardmässig nicht die Originaldatei, sondern schreibt seine Ausgabe auf die Standardausgabe (stdout).

Schreiben der Ausgabe in die Datei "outfile".

$ sed -f scriptfile file > outfile

Schreiben der Ausgabe direkt in die Originaldatei "file".

$ sed -i -f scriptfile file

Schreiben der Ausgabe direkt in die Originaldatei "file", wobei die Originaldatei unter dem Namen "file.bak" erhalten bleibt.

$ sed -i .bak -f scriptfile file

Einfügen der Zeichenfolge "abc" samt Zeilenumbruch (LF) ganz an den Anfang der Datei "datei.txt", sodass diese als erste Zeile erscheint.

$ sed -i '1s/^/abc\n/' datei.txt

Kombination mit anderen Programmen

Angenommen in einem Verzeichnis liegen mehrere Dateien mit Leerzeichen und Bindestrichen im Namen, die man durch Unterstriche ersetzen möchte. Ein solches Skript sollte erst getestet werden. Wenn alles in Ordnung ist, können die Dateien mit dem Befehl mv umbenannt werden.

$ ls -1 *.txt
test 1-0.txt
test 2-5.txt
$ ls -1 *.txt | sed 's/[ -]/_/'
test_1-0.txt
test_2-5.txt
$ for i in *.txt; do mv -v "$i" $(echo $i | sed 's/[ -]/_/'); done
,,test 1-0.txt" -> ,,test_1-0.txt"
,,test 2-5.txt" -> ,,test_2-5.txt"

Zählen aller Worte der Datei "file", in denen doppelte Buchstaben enthalten sind. "(.\)" ist dabei der Zwischenpuffer, "\1" die Puffer-Referenzierung.

$ sed -n '/\(.\)\1/p' file | wc -l

Ersetzen des ersten Zeichens ":" der Datei "file" durch einen Leerschlag.

$ sed 's/:/ /' file

Ersetzen aller Zeichen ":" der Datei "file" durch je einen Leerschlag.

$ sed 's/:/ /g' file

Ersetzen aller Zeichen ":" der Datei "file" durch die Zeichenfolge Leerschlag Doppelpunkt Leerschlag (" : "). Das Zeichen ":" wird dabei in einen Zwischenspeicher geladen und mit "\1" referenziert.

$ sed 's/\(:\)/ \1 /g' file

Ersetzen des Trennzeichens ":" in der Datei "/etc/passwd" durch ein Leerzeichen und Ausgabe auf den Bildschirm. Dafür gibt es zwei Möglichkeiten.

$ sed -e "s,:, ,g" /etc/passwd
$ cat /etc/passwd | sed -e "s,:, ,g"

Ausgabe der ersten fünf Zeilen der Datei "file.txt".

$ sed '5q' file.txt

Ausgabe der Datei "file.txt" ab Zeile 5 bis zum Dateiende.

$ sed -n '5,$p' file.txt

Ausgabe der Zeilen 10 bis und mit 20 der Datei "file.txt".

$ sed -n '10,20p' file.txt

Ausgabe der Datei "file.txt", wobei die vierte und fünfte Zeile gelöscht werden.

$ sed '4,5d' file.txt

Ersetzen der IP-Adresse "10.0.1.1" in allen Dateien im Verzeichnis "/etc" (z. B. wenn gerade eine Maschine geklont wurde) durch die Adresse "10.0.5.5".

$ for i in $(grep -rlIs "10.0.1.1" /etc); do echo "changing file $i"; \
    sed 's/10.0.1.1/10.0.5.5/' $i > sed.tmp; mv sed.tmp $i; done

Einfügen einer Zeile über einem bestimmten Suchmuster.

$ echo "Das ist ein Text\nmit einem SUCHMUSTER" | \
    sed -e '/SUCHMUSTER/{;i\' -e 'der auch in einer Datei stehen könnte' -e '}'
der auch in einer Datei stehen könnte
Das ist ein Text\nmit einem SUCHMUSTER

Auskommentieren aller mit Kleinbuchstaben beginnenden Zeilen in der Datei "file.txt" durch das Zeichen "#".

$ sed "/^[a-z]/s/^/#/" file.txt

Platzhalter

Gegeben sei eine Datei "file" mit folgendem Inhalt.

361
405

Die in der Datei enthaltenen Nummern werden im folgenden Befehl anstelle des Platzhalters "\1" eingesetzt.

$ sed 's/\(.*\)/0000:\1\n9998:\1\n9999:\n/' file > newfile
$ more newfile
0000:361
9998:361
9999:

0000:405
9998:405
9999:

Weblinks

Herausgeber Sprache Webseitentitel Anmerkungen
Sourceforge eng The SED $HOMEwbm
Wikipedia ger Sed (Unix)wbm Enzyklopädischer Artikel
eng The sed FAQwbm
Eric Pement eng Handy oneliners for sedwbm
Stefan Waidele ger sed-Einzeiler : deutsche Übersetzungwbm
Vimperl ger Sedwbm Einige Tips