sed steht für streaming editor und dient dazu, automatisiert Texte zu bearbeiten.

sed
sed
ist ein Kommando mit dem ich mich früher selbst etwas schwer getan habe, aber mit ein bisschen Übung erschließt es ungeahnte Möglichkeiten bei der automatischen Textverarbeitung in Scripts.
manuelle Bearbeitung mit nano
Als Beispieldatei habe ich hier eine Textdatei families.txt mit Namen.
Simpson, Marge
Simpson, Homer
Simpson, Maggie
Simpson, Lisa
Simpson, Bart
#FLANDERS-START
Flanders, Maude
Flanders, Ned
Flanders, Rod
Flanders, Todd
#FLANDERS-END
Wiggum, Sarah
Wiggum, Clancy
Wiggum, Ralph
Die Familie Simpson bekommt vom FBI eine neue Identität im Zeugenschutzprogramm verpasst. Dazu müssen wir bei allem Familienmitgliedern den Nachnamen ändern. Dazu laden wir die Datei in den nano Editor:
nano families.txt
Um Strings zu ersetzen drücken wir CTRL-AltGr-ß gleichzeitig. Das ist mit deutschem Tastaturlayout etwas umständlich, beim amerikanischen ist es einfach nur CTRL-\. nano fragt uns nun nach dem zu suchenden String. Das ist jetzt „Simpson„

Nach einem CR springt nano zum ersten gefundenen Vorkommen des Strings und fragt, wodurch er ersetzt werden soll.

Hier geben wir „Thompson“ ein und bestätigen wieder mit Return. Danach fragt nano, ob wir den aktuellen Fund ersetzen wollen Yes/No oder All mit CTRL-C kann die Aktion abgebrochen werden.

Mit A für All ist die Aufgabe vollbracht.

Ersetzen mit sed
Jetzt stell dir vor, wir müssten innerhalb eines automatischen Scripts diese Ersetzung vornehmen. Da kommt jetzt der sed
ins Spiel. Er bekommt vor dem Dateinamen die Aktion als Parameter übergeben.

Die Aktion sieht etwas kompliziert aus, deshalb nehmen wir das mal auseinander s/Simpson/Thompson/
Wir wollen den String s Simpson ersetzen mit Thompson. Durch das Trennsymbol / werden die einzelnen Bestandteile voneinander abgegrenzt. sed liest jetzt die Datei families.txt und führ die Aktion auf den Inhalt aus. Das Ergebnis wird nach stdout geschrieben. Die Originaldatei bleibt unverändert.
in-place Ersetzung
Möchtest du direkt die Datei ändern, kannst entweder die stdout Ausgabe in die Datei hinein pipen oder du benutzt den Parameter -i für das in-place Replacement
sed -i 's/Simpson/Thompson/' families.txt

Du solltest dabei im Hinterkopf behalten, dass der sed keine Undo-Funktion besitzt, um ein Backup der Originaldatei musst du dich selbst kümmern.
Dies lässt sich aber mit
sed -i.bak 's/Simpson/Thompson/' families.txt
auch automatisieren. Der Parameter -i.bak
weist sed
an, vor der in-place Bearbeitung von families.txt ein Backup unter dem Namen families.txt.bak anzulegen.
Textausgabe ändern
Nehmen wir mal an, du möchtest das Directorylisting deines Homeverzeichnisses veröffentlichen, aber aus Sicherheitsgründen Usernamen und Gruppe ändern. Dazu pipen wir die Ausgabe von ll
einfach in sed
hinein.
ll ~ |sed 's/pi pi/einuser einegruppe/'
Schon sieht niemand mehr, wie User- und Gruppennamen wirklich lauten.

Zeile einfügen
Als nächstes wollen wir noch den Großvater der Simpsons zur Liste hinzufügen.
sed '2a Simpson, Abe' families.txt
Das Kommando 2a
besagt: Füge vor der zweiten Zeile den nachfolgenden Text ein. sed zählt die Zeilen 0-basiert.

Zeile ersetzen
Die Syntax, um eine Zeile zu ersetzen ist ähnlich:
sed '4c Simpson, Lisa Marie' families.txt
Hier wird die Zeile 4 in „Simpson, Lisa Marie“ verändert.

Blöcke ausschneiden
Mit dem Kommando
sed -n '/#FLANDERS-START/,/#FLANDERS-END/p' families.txt
kannst alle Zeilen zwischen den Zeilen FLANDERS-START und FLANDERS-END herausschneiden. Alles andere fällt weg.

Löschen ab Zeile
Du kannst auch sed sagen, ab einer bestimmten Zeile alles zu löschen. Die Familie Wiggum verschwindet mit
sed '12,$d' families.txt

Leerzeilen löschen
Häufig will man Leerzeilen in einer Datei löschen
Dies ist mit
sed '/^$/d' families.txt
Mit dem regulären Ausdruck /^$/d
werden alle Leerzeilen gefunden und dann durch den Leerstring ersetzt. Zu regulären Ausrücken habe ich innerhalb des Pythontutorials schon was geschrieben.

Das Trennzeichen
Beim Trennzeichen (engl.: delimiter) bist du nicht auf den Slash /
festgelegt. Das erste Zeichen nach den s
wird als Trenner definiert und muss dann im weiteren verwendet werden.
Ein anderes Trennzeichen zu verwenden, kann z.B. notwendig sein, wenn der Slash Teil des Suchstrings ist.
Nehmen wir als Beispiel mal an, du benötigst eine Liste aller Dateien unterhalb von /etc
. Die kannst du dir mit
find /etc -type f
geben lassen. Allerdings soll das vorlaufende /etc bei jedem Eintrag weggeschnitten werden. Dann ist der Slash als Delimiter nicht möglich, also benutzen wir einfach ein Komma.
find /etc -type f|sed 's,/etc,,'
Arbeiten mit einem Command file
Zum Abschluss möchte ich dir noch zeigen, wie du mehrere Kommandos für sed
in einer Datei ablegen kannst, um sie wieder zu verwenden.
Wie legen eine Datei commandlist.txt an und schreiben diese beiden sed Kommandos zeilenweise hinein:
s/Simpson/Thompson/
s/Flanders/Flunders/
Das erste Kommando ersetzt, wie oben erklärt, den String Simpson durch Thompson, das zweite tauscht Flanders gegen Flunders aus (dämlicher Flunders 🙂
sed -f commandlist.txt families.txt
Mit diesem Aufruf arbeitet sed
die Kommandos nacheinander ab und wendet sie auf die Datei families.txt an.


Zusammenfassung
Das war jetzt ein wirklich langer Post, daher habe ich dir die Kommandos nochmal tabellarisch zusammengefasst:
Kommando | engl. Bedeutung | Aktion |
---|---|---|
s/$suchstring/$ersatzstring/ | search | Suchen und Ersetzen |
2a $string | add | fügt $string vor Zeile 2 ein. |
4c $string | change | ändert Zeile 4 zu $string |
12,$d | delete | löscht alles ab Zeile 12 |