Für stets wiederkehrende Aufgaben an einer oder mehreren Dateien kann das Arbeiten mit einem reinen Text-Editor schnell mühsam werden. Mit “sed” sparen Sie jede Menge Tipparbeit.
Zu Befehl
Auch wenn sich viele Dinge bequem über grafische Oberflächen wie KDE oder Gnome regeln lassen – wer sein Linux-System richtig ausreizen möchte, kommt um die Kommandozeile nicht herum. Abgesehen davon gibt es auch sonst viele Situationen, in denen es gut ist, sich im Befehlszeilendschungel ein wenig auszukennen.
Der Streamline Editor arbeitet im Gegensatz zu Text-Editoren wie Vi und Emacs nicht interaktiv. Stattdessen definieren Sie vorher auf der Kommandozeile, welche Textbereiche zu löschen, ändern oder einzufügen sind. Bei Bedarf packen Sie auch alle Anweisungen in ein spezielles Skript und führen Sie in einem Rutsch aus. Gilt es in einer oder mehreren Dateien gleich mehrere Zeichen und Zeichenkombinationen zu verändern, verhindert sed, dass Sie sich die Finger wund tippen.
Normalerweise erhält sed die zu bearbeitenden Texte von der Standardeingabe (stdin). Alternativ können Sie eine oder mehrere Dateien angeben: 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. Die generelle Befehlssyntax lautet:
sed [optionen] 'befehl(e)' datei(en)
Damit die Shell den Befehl nicht auswertet, schließen Sie das Kommando in einfache Hochkommas ein. Die Befehle beziehen sich entweder auf einzelne Zeilen, Zeilenbereiche, auf bestimmte Zeichenketten oder – wenn eine derartige Angabe fehlt – auf die ganze Datei. Die Angabe, welche Zeilen zu bearbeiten sind, bezeichnet man als Adresse. Eine Übersicht über die wichtigsten sed-Kommandos mit Adressierungsbeispielen finden Sie in der Tabelle “Sed-Kommandos”.
Sed-Kommandos
| Befehl | Bedeutung | Beispiel |
|---|---|---|
| p | Gibt die entsprechenden Zeilen auf dem Bildschirm aus. | sed -n '1,10p' datei – zeigt nur die ersten zehn Zeilen von datei an. |
| d | Löscht den definierten Bereich. | sed '3d' datei – löscht die dritte Zeile in datei. |
| s | Ersetzt Zeichenketten. | sed 's/KDE/Gnome/' datei – ersetzt alle Vorkommen von “KDE” durch “Gnome” in der gesamten Datei. |
| a | Fügt Text hinter den adressierten Zeilen ein (Einsatz in Skripten). | 1a\ -Umbruch- Hier ist eine neue Zeile. – fügt nach der ersten Zeile den folgenden Text ein. |
| i | Fügt Text vor den adressierten Zeilen ein (Einsatz in Skripten). | 1i\ -Umbruch- Hier ist eine neue Zeile. – fügt vor der ersten Zeile den folgenden Text ein. |
| c | Ersetzt Zeilen oder Zeilenbereiche (Einsatz in Skripten). | 2c\ -Umbruch- Hier ist eine andere Zeile. – ersetzt die zweite Zeile durch den folgenden Text ein. |
| r | Liest den Inhalt einer Datei ein und setzt diesen hinter die entsprechende Adresse. | sed '2r neu.txt' datei – setzt den Inhalt von neu.txt hinter die zweite Zeile von datei . |
| w | Schreibt die adressierten Zeilen oder Bereiche in eine neue Datei. | sed '5,$w neu.txt' datei – speichert von der fünften (einschließlich) bis zur letzten Zeile alles in der Datei neu.txt |
Einfach nur ausgeben
Wie schon erwähnt, wenden Sie sed-Befehle auf so genannte Adressen (bestimmte Zeilen oder Bereich einer Datei) an. Zusammen mit Regular Expressions (siehe auch den Artikel in dieser Ausgabe ab Seite 90) lassen sich Dinge sehr genau treffen. In den folgenden Abschnitten und Beispielen stellt der Artikel für die verschiedenen sed-Kommandos Möglichkeiten zur Adressierung vor – diese gelten dann entsprechend für sämtliche Befehle des Streamline Editors.
Zur einfachen Ausgabe dient das Kommando p. Um beispielsweise die zweite Zeile anzuzeigen, stellen Sie dem Befehl einfach die Ziffer 2 voran:
$ sed '2p' datei Hier ist die erste Zeile. Die zweite Zeile. Die zweite Zeile. Hier steht Zeile 3. …
Die Ausgabe sieht ein bisschen anders aus als erwartet: Statt der zweiten Zeile erscheint die komplette Datei am Bildschirm, die zweite Zeile auch noch zweimal. Um die überflüssigen Ausgaben zu unterbinden, setzen Sie daher zusätzlich die Option -n ein:
$ sed -n '2p' datei Die zweite Zeile.
Löschzug
Auch für das Kommando zum Löschen (d) geben Sie im einfachsten Fall genau eine Zeile an, die bearbeitet werden soll. So löscht das Kommando
sed '1d' datei
die erste Zeile aus datei. Um gleich mehrere Zeilen zu erwischen, schreiben Sie die erste und letzte Zeile durch ein Komma getrennt in den Befehl, Beispielsweise löscht
sed '2,4d' datei
die zweite bis vierte Zeile. Genauso leicht treffen Sie jede n-te Zeile; das Kommando
sed '1~3d'datei
entfernt jede dritte Zeile – ausgehend von der ersten. Wer von der fünften bis zur letzten Zeile der Datei komplett Tabula Rasa machen möchte, muss nicht erst Zeilen zählen und diese dann explizit angeben, sondern kann wieder einen regulären Ausdruck zur Hilfe nehmen. Mit dem Aufruf
sed '5,$d' beispiel.txt
entfernen Sie alle Zeilen ab der einschließlich fünften bis zum Dateiende, welches durch das Dollar-Zeichen definiert wird.
Besonders praktisch erweist sich der Befehl zum Löschen, wenn Sie Konfigurationsdateien in /etc betrachten wollen, die sehr viele Kommentare enthalten. Mit sed löschen Sie einfach alle Zeilen heraus, die ein Rautezeichen am Zeilenanfang haben:
sed '/^#.*/d' /etc/inetd.conf
Als Adresse übergeben Sie dem d-Kommando einen in Schrägstriche eingeschlossenen regulären Ausdruck, der alle Zeilen, die mit einer Raute beginnen und danach keine oder beliebige Zeichen enthalten, bezeichnet. Da auf diese Weise allerdings auch leere Zeilen der Konfigurationsdatei im Terminal landen, können Sie mit einem anderen regulären Ausdruck (^[^#].*) einfach nur diejenigen Zeilen drucken (p-Befehl), die mit einem Zeichen beginnen, das keine Raute ist (Abbildung 1).
Ersetz Dich!
Zusammen mit dem s-Kommando ersetzen Sie Zeichenketten. Nach dem Befehl folgt ein Trennzeichen, das Suchmuster, ein weiteres Trennzeichen, die neu einzufügenden Zeichen und zuletzt ein abschließendes Trennzeichen. Was Sie dabei als Trennzeichen verwenden, steht Ihnen grundsätzlich frei – das Zeichen selbst darf aber nicht im Muster vorkommen. Um in einer Datei jedes Vorkommen des Wortes “Zeile” durch “line” zu ersetzen, können Sie beispielsweise folgendes Kommando darauf loslassen:
$ sed 's/Zeile/line/' datei Hier ist die erste line. Die zweite line, aber hier ist erst das Ende der Zeile. …
Da sed auf diese Weise nur jeweils das erste Vorkommen des Suchmusters in einer Zeile ersetzt, können Sie dem Editor durch den Befehl g mitteilen, dass alle Treffer verwandelt werden sollen:
sed 's/Zeile/line/g' datei
Kommt der hier als Trennzeichen eingesetzte Schrägstrich im Suchmuster selbst vor, weichen Sie auf einen anderen Begrenzer aus, wie etwa die Raute oder das Pipe-Zeichen:
sed 's#http://www.huhnix.net#http://www.huhnix.org#g' url.html
Auch das Substitutionskommando können Sie natürlich nicht nur auf die gesamte Datei loslassen, sondern auch auf einzelne Zeilen. Der Befehl:
sed '1s/Zeile/line/g' datei
sucht und ersetzt nur in der ersten Zeile – auch hier ist das g wieder wichtig, falls es mehr als ein Vorkommen des Musters gibt.
Mehrere Kommandos
Um gleich mehrere Aufgaben mit nur einem sed-Aufruf abzuarbeiten, können Sie den einzelnen Befehlen die Option -e voranstellen. So löschen Sie beispielsweise mit dem folgenden Befehel erst ab der fünften Zeile bis zum Dateiende alles, und lassen auf den Rest der Datei eine Suchen-Ersetzen-Aktion los:
sed -e '5,$d' -e 's/KDE/Gnome/g' datei
Alternativ trennen Sie alle Befehle durch Semikolon voneinander und packen sie in geschweiften Klammern. So lässt sich der letzte Aufruf beispielsweise auch so schreiben:
sed '{5,$d;s/KDE/Gnome/g}' datei
Lesen und Schreiben
Auch zum Einlesen und Speichern bringt sed das passende Kommando mit. Wer beispielsweise eine Datei namens extras hinter der dritten Zeile einfügen möchte, tippt einfach
sed '3r extras' datei
Ebenso leicht lassen sich mit Hilfe des w-Befehls Dinge extrahieren und abspeichern:
sed '1,4w 1bis4.txt' datei
schreibt die ersten vier Zeilen in die neue Datei 1bis4.txt.
Befehlsgewaltig
Bei Bedarf bündeln Sie mehrere sed-Befehle in einer Skript-Datei, die Sie dann mit der Option -f auf die gewünschten Dateien ansetzen. Um beispielsweise aus einer Datei die zweite Zeile zu löschen und eine Zeile nach der vierten zu ergänzen, schreiben sie die Befehle untereinander:
2d 4a\ Nach der vierten Zeile steht hier etwas.
Für das a-Kommando ist wichtig, dass Sie nach dem Befehl selbst (4a) einen Backslash und Zeilenumbruch einfügen. Der neu einzusetzende Text steht in einer neuen Zeile. Handelt es sich um mehr als eine Zeile, müssen Sie jede (bis auf die letzte) mit einem Backslash abschließen:
4a\ Nach der vierten Zeile steht hier etwas.\ Und noch etwas.\ Und noch ein bisschen mehr :)
Soll der neue Text nicht nach einer Zeile erscheinen, sondern vorangestellt werden, wählen Sie statt a den i-Befehl:
1i\ Hier steht etwas Neues… Die so erstellte Befehlsdatei speichern Sie ab (z. B. unter dem Namen <C>skript<C>), übergeben diese dann an <C>sed<C> und bearbeiten eine oder mehrere Dateien damit:
sed -f skript datei
Direkt in die Datei
Wie schon erwähnt, verändert sed standardmäßig nicht das Original, sondern schreibt seine Ausgabe nach stdout. Haben Sie sich überzeugt, dass alle Veränderungen übernommen werden sollen, können Sie die Ausgabe umleiten. Mit dem Operator > schreiben Sie beispielsweise das Ergebnis in eine Datei:
sed -f skript datei > neuedatei
Sollen die Veränderungen ohne Umweg direkt im Original landen, bringt sed dafür den Parameter -i mit. So führt das Kommando
sed -i -f aufgaben datei
dazu, dass sed die Datei mit den Änderungen direkt überscheibt. Auch eine automatische Sicherungskopie erstellt der Parameter auf Wunsch: Fügen Sie einfach direkt an die Option die Dateiendung an, welche das Backup tragen soll:
sed -i.bak -f aufgaben datei
Neben datei – mit den Änderungen – finden Sie anschließend auch das Original unter dem Namen datei.bak im Verzeichnis.
Kombinationsgabe
Besonders praktisch erweist sich sed in Zusammenhang mit anderen Programmen auf der Kommandozeile. Angenommen, in einem Verzeichnis liegen mehrere Dateien mit Leerzeichen und Bindestrichen im Namen, die Sie gerne in Unterstriche umwandeln möchten:
$ ls -1 *.mp3 01 Saor_Free_News from Nowhere.mp3 02 Whirl-Y-Reel.mp3 …
Schreiben Sie in diesem Fall die verschiedenen Ersetzungsregeln für sed einfach in ein Skript:
s/ /_/g s/-/_/g
Natürlich könnten Sie die beiden Zeilen zu einem einzigen regulären Ausdruck s/[ -]/_/g zusammenfassen – das ist für das aktuelle Beispiel aber irrelevant. Das Skript lassen Sie zunächst testweise auf die Dateien los, um zu überprüfen, ob im Ernstfall alles richtig ersetzt wird. Da sed von der Standardeingabe lesen kann, können Sie die Ausgabe des ls-Kommandos also direkt über eine Pipe an den sed-Befehl weiterreichen:
$ ls -1 *.mp3 | sed -f skript 01_Saor_Free_News_from_Nowhere.mp3 02_Whirl_Y_Reel.mp3
Alles richtig? Nun kombinieren Sie das Programm mv zum Umbenennen mit dem Befehl. Damit sed direkt alle Dateien auf einmal erfasst, basteln Sie eine kleine for-Schleife:
$ for i in *.mp3; do mv -v "$i" `echo $i | sed -f skript`; done `01 Saor_Free_News from Nowhere.mp3' -> `01_Saor_Free_News_from_Nowhere.mp3' `02 Whirl-Y-Reel.mp3' -> `02_Whirl_Y_Reel.mp3'
Im Klartext heißt das: Für alle Dateien, die auf *.mp3 enden, mache Folgendes: Verschiebe diese sichtbar in das Ergebnis der sed-Operation. Da in den Original-Dateinamen Leerzeichen enthalten sind, müssen Sie $i in Anführungszeichen einschließen.
Glossar
-
Standardeingabe
-
Linux kennt drei Standardkanäle – “stdin” (Standardeingabe), “stdout” (Standardausgabe) und “stderr” (Standardfehlerausgabe). Laufende Programme erwarten ihren Input von der Standardeingabe, meist über die Tastatur. Die Ausgabe der Programme sehen Sie in der Standardausgabe, also am Bildschirm. Die Standardfehlerausgabe landet in der Regel in der aktiven Konsole: Hier sehen Sie eventuelle Fehlermeldungen des Befehls mit Hinweisen, die zur Problemlösung führen können.
-
Standardausgabe
-
Linux kennt drei Standardkanäle – “stdin” (Standardeingabe), “stdout” (Standardausgabe) und “stderr” (Standardfehlerausgabe). Laufende Programme erwarten ihren Input von der Standardeingabe, meist über die Tastatur. Die Ausgabe der Programme sehen Sie in der Standardausgabe, also am Bildschirm. Die Standardfehlerausgabe landet in der Regel in der aktiven Konsole: Hier sehen Sie eventuelle Fehlermeldungen des Befehls mit Hinweisen, die zur Problemlösung führen können.





