sed
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
|
/^\.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
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
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 |