Mit Sed editieren Sie Textdaten ohne interaktive Benutzeroberfläche – auch in Pipes oder der Eingabeumlenkung. In einer einzigen Zeile lassen sich umfangreiche Editierkommandos absetzen.
Mit dem Stream-Editor Sed [1] bearbeiten Sie Textdateien ohne einen ausgewachsenen Editor. Seine Stärken spielt er insbesondere bei sich wiederholenden Bearbeitungsvorgängen aus, die sich mithilfe von Shell-Skripten automatisieren lassen. Mit regulären Ausdrücken (Englisch: “regular expressions”) steht dem Kommandozeileneditor ein mächtiges Werkzeug zur Seite. Hier übergeben Sie dem Editor eine Beschreibung der Beschaffenheit der zu bearbeitenden Zeichenkette, sodass dieser große Textbestände ohne Zutun automatisiert abarbeitet.
Programmaufruf
Sed nimmt von allen Ecken Kommandos und Daten entgegen: Sie hängen diese entweder an den Aufruf an oder lassen Sed die gewünschten Kommandos aus einer Datei auslesen. Die zu bearbeitenden Daten kommen entweder per Pipe, Eingabeumlenkung oder direkt aus einer Textdatei. Die Ausgabe erfolgt entweder auf auf die Standardausgabe STDOUT (also in der Regel den Bildschirm), per Pipe an den nächsten Befehl oder durch Ausgabeumlenkung in eine Zieldatei. Sed selbst überschreibt hingegen in den Ausgangsdaten nichts.
Listing 1 zeigt eine Reihe von allgemeinen Beispielen. In Zeile 1 liest Sed eine Textdatei ein und gibt das Ergebnis auf der Standardausgabe aus. Im Zeile 2 geschieht dasselbe, allerdings mit Eingabeumlenkung. Zeile 3 zeigt das Anhängen von Sed per Pipe an die Ausgabe eines Programms. In Zeile 4 liest Sed sämtliche Anweisungen aus einer eigens für ihn erstellten Skript-Datei; alternativ geben Sie Sed mehrere Kommandos mit (Zeile 5).
In einigen Fällen wirkt sich die Reihenfolge der Befehle auf das Ergebnis aus. Testen Sie in daher in jedem Fall die Skripte ausgiebig, bevor Sie sie der auf den Datenbestand loslassen. In den Zeilen 6 und 7 leitet Sed seine Ausgabe in eine Zieldatei weiter, wobei im letzten Beispiel auch etwaige Fehlermeldungen dort landen.
Listing 1
$ sed Kommando Textdatei $ sed Kommando < Textdatei $ Programm | sed Kommando | ... $ sed -f Skript ... $ sed -e Kommando1 -e Kommando2 ... -e KommandoN Textdatei $ sed Kommando > Zieldatei $ sed Kommando > Zieldatei 2>&1
Syntax
Sed benötigt für das Editorkommando immer eine oder mehrere Adressen, auf die er das Kommando anwendet, wobei die grundlegende Syntax folgendermaßen aussieht:
$ sed [-Optionen] [Adresse[, weitere Adressen]] [!] Kommando [Argumente]
Als Adressen dienen oft Zeilennummern, wobei $ für die letzte Zeile steht, oder auch reguläre Ausdrücke (/.../). Sed nimmt beliebig viele Adressen entgegen, sofern Sie dabei nicht die Übersicht verlieren. Soll Sed an allen Textstellen außer den adressierten Passagen aktiv werden, kehren Sie eine Adressierung mittels ! einfach um (Negierung). Die Optionen zu Sed und seinen Editierkommandos finden Sie im weiteren Verlauf des Beitrages.
Um mehrere Sed-Kommandos auf einem Rutsch auszuführen, nutzen Sie am besten Sed-Skripte. Diese bestehen aus genau einer Zeile pro Anweisung (Listing 2). Möchten Sie das Skript von der Kommandozeile direkt ausführen, geben Sie /bin/sed in der ersten Zeile als Interpreter-Anweisung (“Shebang”) vor. Die Erste der zwei folgenden Anweisungen entfernt zuerst das Wort “Gans”. Genauer gesagt, tauscht die Anweisung das Wort gegen nichts aus. Die zweite Anwendung ersetzt bei jedem Vorkommen (Option g am Ende der Anweisung) den String “jo” gegen “Jo”.
Listing 2
#!/bin/sed -f s/Gans// s/jo/Jo/g
Machen Sie das Skript ausführbar (etwa über chmod +x Skript), dann lässt es sich wie jedes andere Programm oder Skript direkt von der Kommandozeile aus – ohne das Sed-Kommando davor – aufrufen. Im Regelfall nehmen Sie von dieser Möglichkeit jedoch selten Gebrauch. Vielmehr bringen Sie sed und eventuelle Aufrufe von Skript-Dateien in einem Shell-Skript unter.
Beispieldaten
Für erste Übungen nutzen Sie die in Listing 3 dargestellte Telefonliste. Speichern Sie den Inhalt dieser Tabelle in textdatei.txt ab. Die Tabelle sieht bewusst etwas wüst und zusammengeflickt aus: Leerzeilen, Rechtschreibfehler und andere Makel verunzieren sie. Mit Sed lassen sich diese Fehler jedoch leicht korrigieren – eine große Arbeitserleichterung, besonders dann, wenn es eine Datenbank mit mehreren Tausend Einträgen zu pflegen gilt. Die zweite Spielwiese in Listing 4 beinhaltet eine Liste mit grob unterschiedlich geschriebene Datumsangaben. Auch diese normiert Sed im Handumdrehen. Speichern Sie den Inhalt für den weiteren Gebrauch unter testliste.txt ab.
Listing 3
johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Listing 4
22 April 1984 7.04.1985 30 März 1986 19 April 1987 03.04.1988 26 März 1989 15 April 1990 31-März-1991 19 April 1992 11 April 1993 3 April 1994 16. April 1995 7 April 1996 30 März 1997 12 April 1998
Reguläre Ausdrücke
Beim Ausführen von Sed-Befehlen kommen sehr oft reguläre Ausdrücke zum Einsatz, um Zeichenausdrücke aus dem Text herauszufiltern. Selbst wenn Sie den Ausdruck bisher noch nicht kennen, kennen Sie höchstwahrscheinlich reguläre Ausdrücke schon und nutzen sie regelmäßig: Wildcards wie in ls *.txt entsprechen einem regulären Ausdruck, und Texteditoren bieten über die Suchen-und-Ersetzen-Funktion oft eine Implementation für reguläre Ausdrücke.
In der Regel machen reguläre Ausdrücke jedoch deutlich mehr Arbeit. Mit ein wenig Logik bekommen Sie einfachere Ausdrücke allerdings gut in den Griff. Eine einfache Anweisung lautet zum Beispiel [ABC], sie prüft ob der String auf A, B oder C lautet. Das Konstrukt /ABC/ filtert hingegen auf den zusammenhängenden Begriff “ABC”. Den Aufbau und den Gebrauch regulärer Ausdrücke vollständig zu erklären, würde den Umfang dieses Artikels sprengen, daher finden Sie auf der beiliegenden Heft-DVD einen Artikel zu ersten Schritten mit Regular Expressions aus LinuxUser 06/2015 [2].
Zu so viel Macht reguläre Ausrücke Sed auch verhelfen, so unübersichtlich wachsen die Anweisungen komplexer Aufgaben. Hier hilft oft der Einsatz von Sed-Skripten, die die Aufgabe in mehrere Teile aufspalten. Einige Zeichen innerhalb der Konstrukte gelten zudem sowohl als Sonderzeichen der Shell als auch als Anweisungen für die regulären Ausdrücke. Sie müssen diese deshalb mit dem Zeichen \ für die Shell entwerten oder auf neuhochdeutsch “escapen” (siehe Tabelle “Sonderzeichen”).
Sonderzeichen
| Zeichen | Hinweis Sed-Funktionalität |
|---|---|
( |
öffnet eine Anweisung |
) |
schließt die Anweisung |
{ |
öffnet optionale Anweisung |
} |
schließt optionale Anweisung |
[ |
öffnet Klassenbeschreibung von Zeichen |
] |
schließt Klassenbeschreibung von Zeichen |
" |
maskiert Anweisung und löst Shell-Variable auf |
' |
maskiert eine Anweisung, löst Shell-Variable nicht auf |
` |
schließt Anweisungsblock ein |
. |
ein beliebiges Zeichen außer Zeilenvorschub |
, |
trennt Parameter, etwa Zeilenangaben |
| Leerzeichen | Setzt Markierung (t– und b-Befehl) |
$ |
Dokumentenende, letzte Zeile oder Zeilenende |
& |
Platzhalter für Suchmuster, welches in der Ersetzen-Anweisung mit ausgegeben wird |
| |
oder (Abtrennen von regulären Ausdrücken) |
/ |
Trennzeichen in Editierkommandos |
^ |
Anfang der Zeile, aber: [^Begriff] = Negierung |
\ |
Entwerter |
! |
nach Zeilenzahl: nicht diese Zeile ausgeben |
* |
nie oder beliebig oft |
+ |
Muster mindestens einmal vorhanden |
= |
Ausgabe der Zeilennummer |
\n |
neue Zeile, Zeilenvorschub |
\t |
Tabulator |
Optionen und Kommandos
Verwirrenderweise verfügen sowohl Sed (siehe Tabelle “Sed-Optionen”) als auch die internen Editierkommandos (Tabelle “Editierkommandos”) über eigene Optionen. Wie im Linux-Leben allgemein üblich, teilen Sie dem Stream-Editor die Optionen mit vorangestelltem Minus-Zeichen mit. Den Editieranweisungen übergeben Sie ihre Optionen am Ende des Aufrufs (Tabelle “Optionen der Editierkommandos”).
Sed-Optionen
| Aktion | Option |
|---|---|
| Angabe auszuführender Befehle (Angabe meist unnötig) | -e |
| Auf Datenpufferung verzichten | -u |
| Dateien separat behandeln | -s |
| Erweiterte reguläre Ausdrücke verwenden | -r |
| Sicherungsdatei anlegen | -i[Endung] |
| Skript-Datei einlesen und ausführen | -f Skript |
| Unterdrücken der (nicht betroffenen) Textbereiche | -n |
| Versionsabfrage | -v |
Editierkommandos
| Aktion | Kommando |
|---|---|
| Anfügen von Zeilen oberhalb der angegebenen Stelle | i |
| Anfügen von Zeilen unterhalb der angegebenen Stelle | a |
| Ausgabe der angegebenen Zeilen | p |
| Ausgabe der angegebenen Zeilen optional mit Längenbegrenzung | l [Länge] |
| Austausch von Zeichen | y |
| Sed beenden | q |
| Ersetzen von Text in der angegebenen Zeile | c |
| Löschen der angegebenen Zeilen | d |
| Suchen und Ersetzen | s |
Optionen der Editierkommandos
| Aktion | Option |
|---|---|
| Ausgabe der Zeilennummer | = |
| Betrifft alle Vorkommen | g |
Gibt beim Editierkommando s die geänderte Zeile aus |
p |
| Schreiben der bearbeiteter Zeilen in die Datei | w |
Die Suchfunktion benötigen Sie unter anderem für das Ersetzen von Textteilen. Die Suchangabe stellt hierbei die Adressierung dar. Mithilfe der bereits angesprochenen regulären Ausdrücke erweitern sie die Angaben um Suchmuster. Die Tabelle “Suchmuster und Adressangaben” zeigt als Grundlage eine kleine Auswahl der Möglichkeiten. Einige Praxisbeispiele finden Sie in der Tabelle “Beispielsuchen und Suchmuster”. Sie enthält Fälle, in denen Sed ein Teil des Datenstrom darstellt, als auch Situationen, in denen Sed direkt auf eine Textdatei zugreift.
Suchmuster und Adressangaben
| Aktion | Muster |
|---|---|
| Alle Zeilen | (ohne) |
| Zeile 25 | 25 |
| Nicht Zeile 25 | 25! |
| Zeilen 10 bis 20 | 10,20 |
| Letzte Zeile | $ |
| Nicht Suchmuster | '/Muster/!' |
| Zeichen am Zeilenanfang | ^Zeichen |
| Zeichenkette | /Zeichenkette/ |
| Zeichenmenge | [Zeichenmenge] |
| beliebige Buchstaben | [:alpha:] |
| Kleinbuchstaben | [:lower:] |
| Großbuchstaben | [:upper:] |
| alphanumerische Zeichen | [:alnum:] |
| Zahlen | [:digit:] |
| Hexadezimalzahlen | [:xdigit:] |
| Tabulatoren und Leerzeichen | [:blank:] |
| Leerzeichen | [:space:] |
| Steuerzeichen | [:cntrl:] |
| Druckbare Zeichen (ohne Steuerzeichen) | [:print:] |
| Sichtbare Zeichen (ohne Leertaste) | [:graph:] |
| Satzzeichen | [:punct:] |
Beispielsuchen und Suchmuster
| Gesucht | Suchmuster | Beispiel | Listing |
|---|---|---|---|
| Begriff, Name | '/Begriff/' |
cat textdatei.txt | sed -n '/Meier/p' |
– |
| alle Namen, die “han” oder “Han” beinhalten | '/[Hh]an/p' |
sed -n '/[Hh]an/p' textdatei.txt |
5 |
| Alle Zeilen außer 3 bis 5 | '3,5!' |
sed -n '3,5!'p textdatei.txt |
6 |
| Alle Zeilen, die nicht “Gans” enthalten | '/Gans/!' |
sed -n '/Gans/!'p textdatei.txt |
7 |
| Zeilen, die “H” oder “G” enthalten | '/[H|G]/' |
sed -n '/[H|G]/'p textdatei.txt |
– |
| Zeilen, die “H” oder “G” nicht enthalten | '/[H]\|[G]/!' |
sed -n '/[H]\|[G]/!'p textdatei.txt |
8 |
| Zeile 3 | 3 |
cat textdatei.txt | sed -n '3p' |
– |
| Letzte Zeile | '$p' |
cat textdatei.txt | sed -n '$p' |
– |
| Zeilen nicht ausgeben, die “H” und in der Folge “J” enthalten | '/[H]./,/[J]./!' |
sed -n '/[H]./,/[J]./!'p textdatei.txt |
9 |
| Alle Zeilen, die alphanumerische Zeichen enthalten (Leerzeilen unterdrücken) | '/[:alnum:]/' |
cat textdatei.txt | sed -n '/[:alnum:]/'p |
10 |
Bei zusammengesetzten Adressangaben (ab zwei Suchmustern) verarbeitet Sed alle Zeilen außer der ersten, auf die die erste Adresse zutrifft, bis einschließlich der nächsten Zeile, auf die die zweite Adresse passt. Beachten Sie hierbei das Beispiel aus Listing 9: In der Textdatei textdatei.txt steht ein Eintrag mit kleinem “j” vor dem mit “J”. Das entsprechende Sed-Kommando aus Tabelle “Beispielsuchen und Suchmuster” soll alle Zeilen ausgeben, die “H” und “J” enthalten. In diesem Fall funktioniert das, da die Reihenfolgen im Befehl und in der Textdatei übereinstimmen. Das zweite Beispiel mit den negierten Zeichen “H” und “j” zeigt aber, dass Sed zuerst eine Zeile mit “H” finden muss. Daher gibt Sed den “johann” aus der ersten Zeile trotz des Suchfilters aus.
Listing 5
$ sed -n '/[Hh]an/p' textdatei.txt johann johannson 0885465468798746 Hans Michael 0987654321 Jochen Hansen 0405458765143321
Listing 6
$ sed -n '3,5!'p textdatei.txt johann johannson 0885465468798746 Gabi Gans Meier 0548/9988776655
Listing 7
$ sed -n '/Gans/!'p textdatei.txt johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321
Listing 8
$ sed -n '/[H]\|[G]/!'p textdatei.txt johann johannson 0885465468798746 Klaus Schraube 08755466584
Listing 9
$ sed -n '/[H]./,/[J]./!'p textdatei.txt johann johannson 0885465468798746 Klaus Schraube 08755466584 Gabi Gans Meier 0548/9988776655 $ sed -n '/[H]./,/[j]./!'p textdatei.txt johann johannson 0885465468798746 Klaus Schraube 08755466584
Listing 10
$ cat textdatei.txt | sed -n '/[:alnum:]/'p johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Soll Sed in einem Rutsch mehr als nur einen Filter anwenden, hängen Sie die unterschiedlichen Aufrufe am einfachsten mit einer Pipe hintereinander (Listing 11). Das Kommando unterdrückt entsprechend Listing 10 leere Zeilen und filtert anschließend wie in Listing 7 alle Zeilen mit “Gans” aus der Ausgabe.
Listing 11
$ cat textdatei.txt | sed -n '/[:alnum:]/'p | sed -n '/Gans/!'p johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321
Ersetzen und Löschen
Für das Ersetzen von Zeichenketten in den gefundenen Ausdrücken verwenden Sie die Anweisung s. Die Länge der Zeichenketten für das Suchen und Ersetzen ist dabei unerheblich. Die Syntax der Suchen-und-Ersetzen-Anweisung lautet folgendermaßen:
$ sed -n '[Zeile(n)]s/[Muster]/Ersatz/[Optionen_für_s]' $ sed -n '[/Muster/]s/[Muster]/Ersatz/[Optionen_für_s]'
Der Schalter -n sorgt dafür, dass Sed nur bearbeitete Zeilen ausgibt; das Muster ist optional, wenn Befehl nur auf bestimmte Zeilen angewendet werden soll. Die Tabelle “Optionen für s” führt die entsprechenden Optionen auf.
Optionen für <c>s<c>
| Option | Beschreibung |
|---|---|
g |
Befehl auf alle gefundenen Textstellen in der Zeile anwenden |
p |
Ergebnis der Aktionen ausgeben |
w[Datei] |
Ergebnis in eine Datei schreiben |
Die Suchen-und-Ersetzen-Anweisung beschränken Sie auf bestimmte Zeilennummern, indem Sie vor dem Kommando den Bereich in der Form 5s/Alt/Neu/p (Listing 12, Zeile 1) für eine einzelne Zeile oder in Form von 1,4/Alt/Neu/p (Zeile 2) einen Bereich angeben. Mit einem Ausrufezeichen kehren Sie die Auswahl um (Zeile 3). Weiterhin lässt sich die Anweisung unabhängig von der Suchen- beziehungsweise Ersetzen-Vorschrift auf Zeilen beschränken, die eine bestimmte Zeichenkette oder Struktur aufweisen (Zeile 4). Möchten Sie die gesuchte Zeichenkette gleich löschen, dann geben Sie Sed eine leere Ersetzungsanweisung mit.
Listing 12
$ sed -n '5s/Alt/Neu/p' [Datei] $ sed -n '1,4/Alt/Neu/p' [Datei] $ sed -n '20-80!s/Alt/Neu/p' [Datei] $ sed -n '/[Zeichenkette|Muster]/s/Alt/Neu/gp' [Datei]
Grundsätzlich bearbeitet Sed jeweils das erste Auftreten des Suchmusters in einer Zeile. Soll der Editor jedoch an alle passenden Fundstellen Hand anlegen, fügen Sie am Ende der Anweisung die Option g (wie “gesamt”) hinzu. Im Normalfall gibt Sed Feedback zu den jeweiligen Arbeitsschritten aus. Diese Ausgabe unterdrücken Sie mit der Option -n und verwandeln den Stream-Editor so in einen stummen Diener. Gesprächiger wird Sed hingegen mit der Option p wie (“print”). Alternativ schreiben Sie die Ergebnisse in eine neue Ausgabedatei. Zusammen mit der Option w geben Sie eine Zieldatei an. Die Tabelle “Beispiele: Suchen und Ersetzen” zeigt einige kürzere Beispiele.
Beispiele: Suchen und Ersetzen
| Aktion | Beispiel | Listing |
|---|---|---|
| Suchmuster nur beim ersten Auftreten ersetzen | cat textdatei.txt | sed -n 's/j/J/p' |
13 |
| Suchmuster bei jedem Auftreten ersetzen | cat textdatei.txt | sed -n 's/j/J/gp' |
13 |
| Löschen des Wortes “Gans” | sed -n 's/Gans//gp' textdatei.txt |
14 |
| Ersetzen von “Hans” durch “Jens” in der Zeile 4 | cat textdatei.txt | sed -n '4s/Hans/Jens/gp' |
15 |
| Ersetzen von “09” durch “089” bei allen Zeilen mit der Zeichenkette “ans” | sed -n '/ans/s/09/089/gp' textdatei.txt |
16 |
| Ersetzen von “0” durch “089” bei allen Zeilen, außer sie enthalten die Zeichenkette “ans” | sed -n '/ans/!s/0/089/gp' textdatei.txt |
17 |
| Löschen aller Zahlen mitsamt Schrägstrichen | cat textdatei.txt | sed -n s'/[0-9\/]//'gp |
18 |
Listing 13
$ cat textdatei.txt | sed -n 's/j/J/p' Johann johannson 0885465468798746 $ cat textdatei.txt | sed -n 's/j/J/gp' Johann Johannson 0885465468798746
Listing 14
$ sed -n 's/Gans//gp' textdatei.txt Gabi Meier 0548/9988776655
Listing 15
$ cat textdatei.txt | sed -n '4s/Hans/Jens/gp' Jens Michael 0987654321
Listing 16
$ sed -n '/ans/s/09/089/gp' textdatei.txt Hans Michael 08987654321
Listing 17
$ sed -n '/ans/!s/0/089/gp' textdatei.txt johann johannson 089885465468798746 Klaus Schraube 0898755466584
Listing 18
$ cat textdatei.txt | sed -n s'/[0-9\/]//'gp johann johannson Klaus Schraube Hans Michael Jochen Hansen Gabi Gans Meier
Ein komplexeres Beispiel finden Sie in Listing 19. Die über mehrere Zeilen per Pipe verknüpften Sed-Aufrufe bringen die uneinheitlich geschriebenen Datumsangaben aus der Datei testliste.txt in eine normierte Form. Beim Eingeben eines solchen Kettenbefehls müssen Sie darauf achten, nach dem Rückstrich \ am Ende die Zeile sofort umzubrechen und nicht noch ein Leerzeichen anzuhängen. Alternativ lassen Sie den Zeilenumbruch weg und fahren umgehend mit dem Pipe-Zeichen der Folgezeile fort.
Listing 19
$ cat testliste.txt \| sed '/^[\ ]/'s'/\ /0/'p \| sed s'/-/ /'pg \| sed s'/März/03./'p \| sed s'/April/04./'p \| sed s'/^\([0-3][0-9]\ \)/&./'p \| sed s'/\ //'gp \| uniq 22.04.1984 07.04.1985 30.03.1986 [...]
Der Aufruf von cat in Zeile 1 liest die Liste aus der Datei aus und füttert sie am am Anfang von Zeile 2 in die Pipe. Das erste Sed-Kommando in Zeile 2 ersetzt führende Leerzeichen durch die Ziffer “0”. Zeile 3 tauscht Minuszeichen in den Datumsangaben gegen Leerzeichen. Die Aufrufe von Sed in den Zeilen 4 und 5 ersetzen nun den in Worten geschriebenen Monat durch den passenden numerischen Wert und hängen einen Punkt an – für ein vollständiges Kalender-Skript müssten Sie dies für jeden Kalendermonat erledigen.
Die Anweisung in Zeile 6 ist nun nicht mehr ganz so einfach zu durchblicken. Sie ersetzt alle am Zeilenanfang stehenden (^), zweistelligen Zahlen (die erste Stelle mit Ziffern von 0 bis 3, die zweite Stelle mit allen Ziffern) und einem Leerzeichen durch sich selbst (&) und einen Punkt. Damit die Wiederholung des Suchbegriffs für das Ersetzen funktioniert, setzen Sie den Bereich in runde Klammern, die Sie allerdings mit einem Backslash \ entwerten müssen.
Die Sed-Anweisung der Zeile 7 entfernt nun sämtliche Leerzeichen (g als Option von s) aus dem restlichen Text. Mit uniq aus Zeile 8 entfernen Sie am Ende noch jede mehrfach aufeinander folgende, zum Vorgänger identische Zeile, sodass Sie nun eine sauber normierte und formatierte Liste mit Datumsangaben erhalten.
Das Übernehmen des zu ersetzenden Musters in den Ersatzbegriff erspart in der Praxis viel Arbeit, daher macht ein etwas ausführlicherer Blick auf diese Funktion Sinn. Das Sed-Kommando aus der ersten Zeile von Listing 20 macht aus “schraube” das Wort “abschrauben”. Ähnlich funktioniert das Umwandeln von Klein- in Großbuchstaben (Zeile 3). Das \U vor & signalisiert die Anweisung für die Ausgabe in Großbuchstaben. Für den umgekehrten Weg verwenden Sie zum Suchen [[:upper:]] und die Anweisung \L. Beide Beispiele kombiniert ergeben dann aus dem orthografisch korrekten Hauptwort “Schraube” das Verb “abschrauben” (Zeile 9).
Listing 20
$ echo "schraube" | sed -n s'/schraube/ab&n/'p abschrauben $ cat textdatei.txt | sed -n s'/\([[:lower:]]\)/\U&/'pg JOHANN JOHANNSON 0885465468798746 KLAUS SCHRAUBE 08755466584 HANS MICHAEL 0987654321 JOCHEN HANSEN 0405458765143321 GABI GANS MEIER 0548/9988776655 $ echo "Schraube" | sed -n s'/Schraube/ab&n/'p | sed -n s'/\([[:upper:]]\)/\L&/'pg abschrauben
Für Zeichenfilter und andere Anwendungen verwenden Sie diese Option y. Führen Sie in diesem Fall im Suchmuster-Teil alle Zeichen einzeln auf, die Sed austauschen soll. Der Ersetzen-Teil sollte aus der selben Anzahl an Zeichen bestehen. Der Kommandoaufbau kennt keine weiteren Optionen, auch sollten Sie -n weglassen. Das einfache Beispiel sed y'/a/b/' würde etwa sämtliche “a” im Text gegen “b” tauschen.
Listing 21 wendet die Option in einem etwas komplexeren Beispiel auf textdatei.txt an. Das Kommando ersetzt in allen Zeilen, die mit “j” beginnen, kleine “j” durch den Großbuchstaben. Dabei gilt es aber darauf zu achten, dass Sed in diesem Fall den Buchstaben auch innerhalb eines Wortes in einen Großbuchstaben verwandeln würde.
Listing 21
$ cat textdatei.txt | sed '/^j/'y'/j/J/' Johann Johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Komplette Zeilen
Beim Austausch einer kompletten Zeilen greifen Sie auf die Sed-Option c zurück. Allgemein tauschen Sie mit sed 'Suche'c'Ersatz' die über den Suchbegriff herausgefilterte Zeile vollständig gegen den Ersatzbegriff aus. Das Beispiel aus Listing 22 löscht die Leerzeile und trägt stattdessen einen Trenner in Form einer Reihe von Minuszeichen ein.
Listing 22
$ cat textdatei.txt | sed '/^\ *$/'c'---' johann johannson 0885465468798746 --- Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Anstelle des Suchmusters nimmt Sed allgemein mit sed [Zeile(n)]c'Ersatz' an dieser Stelle auch Zeilennummern an. Das erste Beispiel aus Listing 23 ersetzt die Leerzeile in Zeile 2 von textdatei.txt durch einen Balken mit Rauten. Beachten Sie bei der Angabe mehrerer Zeilennummern, dass Sie diese und alle anderen aus diesem Bereich löschen und mit der Austauschzeile ersetzen. Das Beispiel aus Zeile 8 löscht die Zeilen 2 bis 4 aus dem Inhalt von textdatei.txt und setzt an deren Stelle den Ersatztext ein.
Listing 23
$ cat textdatei.txt | sed 2c'###' johann johannson 0885465468798746 ### Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655 $ cat textdatei.txt | sed 2,4c'Restliche Mitglieder' johann johannson 0885465468798746 Restliche Mitglieder Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Soll Sed gleich ganze Zeilen aus dem Inhalt entfernen, verwenden Sie die Sed-Option d. Die zu löschenden Zeilen sprechen Sie über ein Suchmuster an, wie etwa sed '/Muster/'d. Alternativ geben Sie direkt die Zeilennummer(n) der nicht mehr erwünschten Zeilen an: sed Zeile(n)d. Die Beispiele aus Listing 24 löschen die Leerzeile aus textdatei.txt oder entfernen ohne weitere Umwege die vierte Zeile aus dem Inhalt.
Listing 24
$ cat textdatei.txt | sed '/^\ *$/'d johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655 $ cat textdatei.txt | sed 4d johann johannson 0885465468798746 Klaus Schraube 08755466584 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655
Inhalte einfügen
Mit der Anweisung a fügen Sie zusätzliche Zeilen unterhalb, mit i oberhalb der angegeben Zeile oder des Suchmusters ein. Für die Positionierung nutzen Sie ein Suchmuster oder geben direkt eine Zeilennummer an. Führen Sie mehrere Zeilennummern an oder passt das Suchmuster gleich auf mehrere Zeilen, wendet Sed die Anweisung auf jede passende Zeile an.
Listing 25 zeigt zwei Beispiele zum Einfügen von Inhalten: Das erste Kommando ab Zeile 1 fügt am am Anfang und am Ende der Ausgabe (definiert über $) jeweils eine neue Zeile ein. Das Kommando ab Zeile 12 sucht hingegen nach dem String “Gans” und fügt dann um diesen herum jeweils die vorbereitete Textzeile ein. In der Praxis erstellen Sie so zum Beispiel manuell zu bearbeitende Prüflisten.
Listing 25
$ cat textdatei.txt \| sed '1i NEU ERSTE ZEILE NEU'\| sed '$a NEU LETZTE ZEILE NEU' NEU ERSTE ZEILE NEU johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 Gabi Gans Meier 0548/9988776655 NEU LETZTE ZEILE NEU $ sed '/Gans/'i'---- DATEN ÜBERPRÜFEN ----' textdatei.txt\| sed '/Gans/'a'----' johann johannson 0885465468798746 Klaus Schraube 08755466584 Hans Michael 0987654321 Jochen Hansen 0405458765143321 ---- DATEN ÜBERPRÜFEN ---- Gabi Gans Meier 0548/9988776655 ----
Soll Sed per Skript eine Shell-Variable entgegennehmen und korrekt auflösen, müssen Sie die Anweisungen in Anführungszeichen (") anstelle eines Hochkommas (') setzen. Das kleine Shell-Skript in Listing 26 zeigt exemplarisch die Handhabung von Shell-Variablen. Es fragt per read einen Suchbegriff ab und durchforstet anschließend textdatei.txt nach diesem String. Listing 27 zeigt den Ablauf des Skripts im Terminal.
Listing 26
#! /bin/sh echo -n "Suchbegriff eingeben: "; read eingabe cat textdatei.txt | sed -n "/$eingabe/"p
Listing 27
$ ./musterskript.sh Suchbegriff eingeben: Hansen Jochen Hansen 0405458765143321
Fazit
Mit Sed gelingen Textmanipulationen ohne Benutzereingriff vollautomatisch. Eine durchaus kryptische Syntax erschwert anfangs den schnellen Gebrauch. Bauen Sie deshalb Ihre Skripte schrittweise auf.
Infos
[1] Projektseite: http://sed.sourceforge.net/
[2] Regular Expressions: Frank Hofmann, “Schnipseljagd”, LU 06/2015, S. 10, http://linux-community.de/35006





