Sed/Suchen und Ersetzen

Aus Foxwiki

Suchen und Ersetzen

In diesem Falle steht das Trennzeichen "/" an drei Stellen: vor und hinter der RE, also dem Suchmuster und hinter dem Ersetzungsmuster.

Der mittlere Schrägstrich ist also Ende-Delimiter für die RE und gleichzeitig Anfangs-Delimiter für den Ersetzungsstring.

Logischer Weise müsste der Schrägstrich viermal vorkommen, aber sed hat die beiden mittleren Schrägstriche zu einem verschmolzen.

Zeichen ersetzen [s]

Das dem s-Kommando folgende Zeichen wird als Trennzeichen angesehen.

Anschließend folgt das Suchmuster und, getrennt durch das Trennzeichen, das Ersatzmuster, welches wiederum mittels des Trennzeichens abgeschlossen wird.

Prinzipiell kann jedes druckbare Zeichen als Trennzeichen Verwendung finden, es selbst darf allerdings kein Bestandteil eines Musters sein!

Eine Substitution sieht demnach wie folgt aus:

sed 's/altes Muster/neues Muster/' datei
sed 's?altes Muster?neues Muster?' datei

Im Beispiel ersetzen wir »RegEx« durch »Regulärer Ausdruck«:

sed 's#RegEx#Regulärer Ausdruck#' test.txt
 1 Der Aufruf des Stream Editors besitzt immer das Format:
 2 
 3 sed 'Kommando' Dateiname
 4 
 5 Dabei kann dem Kommando mitgeteilt werden, welche Zeilen der
 6 Eingabedatei es bearbeiten soll. 
  • Als Adressierung kommen folgende
 7 Mechanismen in Frage:
 8 
 9 Keine Angabe Alle Zeilen 
 10 Nummer Genau diese Zeile 
 11 Start, Ende Alle Zeilen von "Start" bis "Ende" 12 $ Symbolisiert die letzte Zeile 
 13 Regulärer Ausdruck Zeilen, die den Regulären Ausdruck enthalten
 14 1, Regulärer Ausdruck Von Zeile 1 bis zur ersten Zeile, die RegEx enthält

Globale Substitution

Wer genau hinschaut, wird im letzten Beispiel eine fehlende Ersetzung von »RegEx« bemerkt haben (Zeile 14).

  • Der Editor bearbeitet in jeder Zeile nur das erste Vorkommen.
  • Um alle Muster zu ersetzen, ist das Kommando »g« nachzustellen:
sed -n 's#RegEx#Regulärer Ausdruck#gp' test.txt
 13 Regulärer Ausdruck Zeilen, die den Regulären Ausdruck enthalten
 14 1, Regulärer Ausdruck Von Zeile 1 bis zur ersten Zeile, die Regulärer Ausdruck enthält

Da wir nur an den modifizierten Zeilen interessiert sind, haben wir das Sed mitgeteilt (Option -n).

Allerdings würde nun das Substitutionskommando die gesamte Ausgabe unterdrücken, hätten wir dem nicht mit dem p-Kommando entgegen gewirkt.

Speichern von Mustern und den späteren Zugriff darauf

Es soll die Numerierung der Zeilen von Einer- auf Zehnerschritte erhöht werden:

sed 's/^\(space:*[1-9]\{1,\}\)/\10/' test.txt
 10 Der Aufruf des Stream Editors besitzt immer das Format:
 20 
 30 sed 'Kommando' Dateiname
 40 
 50 Dabei kann dem Kommando mitgeteilt werden, welche Zeilen der
 60 Eingabedatei es bearbeiten soll. 
  • Als Adressierung kommen folgende
 70 Mechanismen in Frage:
 80 
 90 Keine Angabe Alle Zeilen
 100 Nummer Genau diese Zeile
 110 Start, Ende Alle Zeilen von "Start" bis "Ende"
 120 $ Symbolisiert die letzte Zeile
 130 RegEx Zeilen, die den Regulären Ausdruck enthalten
 140 1, RegEx Von Zeile 1 bis zur ersten Zeile, die RegEx enthält* Das Beispiel profitiert von dem Wissen, dass die Zeilenummer am Beginn der Zeile zu finden ist. 
  • Das Muster, dem unser Interesse gilt, sind alle Ziffern zu Beginn der Zeile, wobei führende Leerzeichen durchaus möglich sind.
  • Genau jenes Muster merken wir uns für den späteren Gebrauch vor, indem wir es in »\(...\)« einschließen.
  • Der Zugriff auf dieses erste gespeicherte Muster im Ersatzmuster erfolgt durch »\1«.
    Bis zu 9 Muster lassen sich pro Zeile speichern, die entsprechend ihrer Reihenfolge mittels \1, \2,... \9 referenziert werden.

Beispiel

"isst" soll in allen Zeilen durch "ist" ersetzt werden.

  • Eigentlich müssten pro String ein Anfangs-/Ende-Delimiter verwendet werden.
/isst//ist/
  • beide Strings müssten durch "/" begrenzt werden
  • sed verschmilzt die mittleren Schrägstriche zu einem!
/isst/ist/
  • # dies erscheint zunächst unlogisch.

Der Befehl "s" für "suchen & ersetzen" steht vor(!) der RE.

sed 's/isst/ist/' < sed-test.txt 
  • Befehl "s" steht am Anfang!
  • sed selektiert alle Zeilen, in denen "isst" vorkommt, ersetzt "isst" durch "ist"
  • und gibt das Ergebnis am Bildschirm aus

Um die Änderungen in die Datei zu schreiben, gibt es zwei Möglichkeiten:

mit Hilfe einer temporären Datei
sed 's/isst/ist/' < sed-test.txt > sed-test2.txt * Ausgabe in temporäre Datei umleiten
vim sed-test2.txt* Ergebnis kontrollieren!
mv sed-test2.txt sed-test.txt* Originaldatei ersetzen durch temporäre Datei
direkt
sed -i 's/isst/ist/' sed-test.txt* Vorsicht, Änderungen werden direkt in Datei geschrieben!

Im Beispiel würde sed in jeder Zeile nur das erste gefundene "isst" durch "ist" ersetzen.

  • Um zu erreichen, dass alle Fundstellen geändert werden, muss ans Ende der Anweisung der g-Spezifizierer (=global) gesetzt werden:
sed 's/isst/ist/g' < sed-test.txt

Selektives Suchen und Ersetzen

Beim "normalen" Suchen und Ersetzen werden alle Zeilen in den Suchvorgang einbezogen.

  • Es kommt jedoch vor, dass die Ersetzung nur innerhalb eines bestimmten Bereiches erfolgen soll.
  • Die Bereichsauswahl kann, wie oben beschrieben, über eine RE oder explizit erfolgen.

Beispiel

Ans Ende aller Zeilen, in denen "isst" vorkommt, soll " --Fehler!" angehängt werden.

  • Das normale Suchen und Ersetzen hilft hierbei nicht weiter, denn "isst" soll ja nicht ersetzt werden, sondern dient nur Selektion der Zeilen, an die das Suffix angehängt werden soll.

Es sind also zwei Vorgänge erforderlich:* Bereichsauswahl über die RE "/isst/"

  • Suchen des Zeilenendes und ersetzen durch " --Fehler!".

Genau genommen wird nicht das Zeilenende ersetzt, sondern ein gedachte fiktives "leer-Zeichen" (sozusagen "") vor dem Zeilenende.

Damit sed weiß, dass sich Suchen und Ersetzen nur auf die Bereichsauswahl bezieht, steht es hinter der Bereichsauswahl in geschweiften Klammern.

  • Sie können auch weggelassen werden.
  • Ich rate jedoch dazu, sie zu verwenden, da die Logik des Befehls dadurch klarer wird.
sed '/isst/{s/$/ --Fehler!/}' < sed-test.txt
* /isst/ -> Bereichsauswahl über RE
* {...} -> Anweisung in "{...}" bezieht sich auf die vorangestellte Bereichsauswahl
* $ -> Platzhalterzeichen für "Zeilenende" (in Suchen & Ersetzen Anweisungen)
* s/$/ --Fehler!/ -> fiktives "leer-Zeichen" vor dem Zeilenende wird ersetzt durch " --Fehler!"

Bei expliziter Bereichsauswahl funktioniert dies analog.

Beispiel

Ans Ende der 2.

  • und 3.
  • Zeile soll " --Fehler!" gesetzt werden.
sed '2,3{s/$/ --Fehler!/}' < sed-test.txt
  • 2,3 -> explizite Bereichsauswahl: Zeile 2-3

Beachten Sie, dass die explizite Bereichsauswahl durch keine Delimiterzeichen "/" eingegrenzt ist.

Beispiel

Ans Ende der letzten Zeile soll " --Ende" gesetzt werden.

sed '${s/$/ --Fehler!/}' < sed-test.txt
  • # $ -> explizite Bereichsauswahl; "$" steht hier für "letzte Zeile"

Beispiel

an den Anfang der ersten Zeile soll "Anfang--" gesetzt werden.

sed '1{s/^/Anfang--/}' < sed-test.txt
  • 1 -> explizite Bereichsauswahl
  • ^ -> Platzhalterzeichen für "Zeilenanfang"
  • ein fiktives "leer-Zeichen" ("") am Zeilenanfang wird ersetzt durch "Anfang--"

Der vorige Befehl funktioniert auch ohne {}, ist aber schwerer zu lesen:

sed '1s/^/Anfang--/' < sed-test.txt

Control-Character

Mit Hilfe von sed können verschiedenste Konvertierungen durchgeführt werden, zum Beispiel von DOS- (CR-LF) zix Dateiendezeichen (LF).

  • Control-Character können entweder als escape-character oder als hexadezimal-character dargestellt werden.

Wichtige control-character

Bezeichnung escape hex "cat -A" linefeed \n \x0a $ carriage-return \r \x0d ^M tab \t \x09 ^I

Kontrollzeichen innerhalb von Variablen lassen sich auch sehr gut mit Hilfe des l-Befehls von sed am Bildschirm darstellen.

  • Dies ist eine Alternative zu "cat -A"
a=$'Tabulator: \x09 CR: \x0d LF: \x0a'
echo -e "$a" | sed -n 'l'

Escape-character

a="Zeile1\r\nZeile2" 

am Ende von Zeile1 steht CR-LF (=DOS-Zeilenende)

echo -e "$a" | cat -A 

Inhalt wird inkl.

  • Kontrollzeichen ausgegeben und darstellbar gemacht (cat -A), der carriage-return wird als ^M dargestellt (0x0D)
echo -e "$a" | sed 's/\r//' | cat -A

der carriage-return wird durch "leer" ersetzt, ^M wird nicht mehr angezeigt

unset a

Hexadezimal-character

a=$'Zeile1\x0d\x0aZeile2' 

am Ende von Zeile1 steht CR-LF (0x0d+0x0a)

echo -e "$a" | cat -A
 echo -e "$a" | sed 's/\x0d//' | cat -A 
 unset a

Beispiele

Text in Dateien mit RegEx

In this article let us review how to use sed substitute command “s”. 
  • The `s’ command is probably the most important in `sed’ and has a lot of different options.
The `s’ command attempts to match the pattern space against the supplied REGEXP; if the match is successful, then that portion of the pattern space which was matched is replaced with REPLACEMENT. 
Syntax: 
#sed 'ADDRESSs/REGEXP/REPLACEMENT/FLAGS' filename 
 
  • s is substitute command
  • / is a delimiter
  • REGEXP is regular expression to match
  • REPLACEMENT is a value to replace


g Replace all the instance of REGEXP with REPLACEMENT 
  • n Could be any number,replace nth instance of the REGEXP with REPLACEMENT.
  • p If substitution was made, then prints the new pattern space.
  • i match REGEXP in a case-insensitive manner.
  • w file If substitution was made, write out the result to the given file.
  • We can use different delimiters ( one of @ % ; : ) instead of /


Let us first create thegeekstuff.txt file that will be used in all the examples mentioned below. 
cat thegeekstuff.txt 
# Instruction Guides 
1. 
  • Linux Sysadmin, Linux Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Linux
5. 
  • Productivity (Too many technologies to explore, not much time available)
# Additional FAQS 
6. 
  • Windows- Sysadmin, reboot etc.
Let us review some interesting examples for substitution now. 

Ersetzen von “Linux” durch “Unix” (s)

In the example below, in the output line “1. 
  • Linux-Unix Sysadmin, Linux Scripting etc” only first Linux is replaced by Linux-Unix.
  • If no flags are specified the first match of line is replaced.
sed 's/Linux/Unix/' thegeekstuff.txt 
# Instruction Guides 
1. 
  • Unix Sysadmin, Linux Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Unix
5. 
  • Productivity (Too many technologies to explore, not much time available)
# Additional FAQS 
6. 
  • Windows- Sysadmin, reboot etc.

Alle Treffer ersetzen (s//g)

The below sed command replaces all occurrences of Linux to Linux-Unix using global substitution flag “g”. 
sed 's/Linux/Linux-Unix/g' thegeekstuff.txt 
# Instruction Guides 
1. 
  • Linux-Unix Sysadmin, Linux-Unix Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Linux-Unix
5. 
  • Productivity (Too many technologies to explore, not much time available)
# Additional FAQS 
6. 
  • Windows- Sysadmin, reboot etc.

Jeden zweiten Treffer ersetzen (s//2)

In the example below, in the output line “1. 
  • Linux Sysadmin, Linux-Unix Scripting etc.” only 2nd occurance of Linux is replaced by Linux-Unix.
sed 's/Linux/Linux-Unix/2' thegeekstuff.txt 
# Instruction Guides 
1. 
  • Linux Sysadmin, Linux-Unix Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Linux
5. 
  • Productivity (Too many technologies to explore, not much time available)
# Additional FAQS 
6. 
  • Windows- Sysadmin, reboot etc.

Nur ersetzen, wenn eine Zeile einen Treffer ergibt

In this example, if the line matches with the pattern “-”, then it replaces all the characters from “-” with the empty. 
sed '/\-/s/\-.*//g' thegeekstuff.txt 
# Instruction Guides 
1. 
  • Linux Sysadmin, Linux Scripting etc.
2. 
  • Databases
3. 
4. 
5. 
# 
6. 
Security (Firewall, Network, Online Security etc) 
Storage in Linux 
Productivity (Too many technologies to explore, not much time available) 
Additional FAQS 
Windows 

Letzten X Zeichen jeder Zeile löschen

This sed example deletes last 3 characters from each line. 
sed 's/...$//' thegeekstuff.txt 
# Instruction Gui 
1. 
  • Linux Sysadmin, Linux Scripting e
2. 
  • Databases - Oracle, mySQL e
3. 
  • Security (Firewall, Network, Online Security e
4. 
  • Storage in Li
5. 
  • Productivity (Too many technologies to explore, not much time availab
# Additional F 
6. 
  • Windows- Sysadmin, reboot e

Kommentare löschen

Delete all the comment lines from a file as shown below using sed command. 
sed -e 's/#.*//' thegeekstuff.txt
1. 
  • Linux Sysadmin, Linux Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Linux
5. 
  • Productivity (Too many technologies to explore, not much time available)
6. 
  • Windows- Sysadmin, reboot etc.

Kommentare und leere Zeilen löschen

In this example, there are two commands seperated by ‘;’ 
First command replaces the lines starting with the # to the blank lines 
Second command deletes the empty lines. 
sed -e 's/#.*//;/^$/d' thegeekstuff.txt
1. 
  • Linux Sysadmin, Linux Scripting etc.
2. 
  • Databases - Oracle, mySQL etc.
3. 
  • Security (Firewall, Network, Online Security etc)
4. 
  • Storage in Linux
5. 
  • Productivity (Too many technologies to explore, not much time available)
6. 
  • Windows- Sysadmin, reboot etc.

Zeilenwechsel konvertieren

DOS newlines (CR/LF) ins Unix-Format ändern
Copy the DOS file to Unix, you could find \r\n in the end of each line. 
This example converts the DOS file format to Unix file format using sed command. 
$sed 's/.$//' filename

Rekursives Suchen und Ersetzen

Ersetzen einer Zeichenkette in allen Daten einer Verzeichnisstruktur.

find . -type f -print0 | xargs -0 -n 1 sed -i -e "s/suche/ersetze/g"
Beispiel mit escape Zeichen \
‘typo3temp/pics ersetzen mit ‘../../typo3temp/pics
find . -name *.html -type f -print0 | xargs -0 -n 1 sed -i -e \ "s/’temp\/pics/’..\/..\/temp\/pics/g"

HTML Tags aus Datei entfernen

In this example, the regular expression given in the sed command matches the html tags and replaces with the empty.

sed -e 's/<[^>]*>//g'

This is an example. This is an example.