Das sed Kommando – bash Tutorial Teil 21

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

Dr. Dirk Colbry, Michigan State
Gnu-bash-logoCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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

Olli Graf - raspithek.de
searching-in-nanoCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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

Olli Graf - raspithek.de
replace-withCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
confirm-replaceCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

Mit A für All ist die Aufgabe vollbracht.

Olli Graf - raspithek.de
replace-completedCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
sed-exampleCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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
Olli Graf - raspithek.de
sed-iCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
hide-user-and-groupCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
sed-appendCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
sed-changeCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
sed-blockCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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
Olli Graf - raspithek.de
sed-delete-from-lineCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
sed-delete-blank-linesCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=

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.

Olli Graf - raspithek.de
commandlistCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Ausgabe nach Abarbeitung der commandlist.txt
Ausgabe nach Abarbeitung der commandlist.txt Datei
Olli Graf - raspithek.de
commandlistCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . loading=
Ausgabe nach Abarbeitung der commandlist.txt Datei

Zusammenfassung

Das war jetzt ein wirklich langer Post, daher habe ich dir die Kommandos nochmal tabellarisch zusammengefasst:

Schreibe einen Kommentar

Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
{}
Nothing to preview
Insert
Creative Commons License
Except where otherwise noted, the content on this site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Olli Graf - raspithek.de