März 2014: Reguläre Ausdrücke mit dem Stream-Editor sed

Autoren: Michael Gisbers und Christian Hesse

Reguläre Ausdrücke sind Thema bei den Lerninhalten der folgenden LPI Prüfungen:

  • Linux Essentials: 3.2 Suche und Entnahme von Daten aus Dateien
  • LPI 101: 103.7 Textdateien mit regulären Ausdrücken durchsuchen

Im vorletzten Artikel haben wir uns mit dem Stream-Editor `sed` vertraut gemacht, danach folgte ein Überblick im Bereich der Regulären Ausdrücke. In diesem Artikel wollen wir schließlich das gelernte Wissen kombinieren und uns Reguläre Ausdrücke in `sed` zu Nutze machen.

Spezialfall Regulärer Ausdruck?

Bisher haben wir in `sed` lediglich einfache Zeichenketten genutzt. Genau genommen ist eine Zeichenkette auch nichts anderes als ein Regulärer Ausdruck: Die Zeichenkette ist eine 'Verkettung' der einzelnen Buchstaben, Ziffern und Zeichen, aus denen sie besteht. Damit sind Reguläre Ausdrücke kein Sonderfall und ohne zusätzliche Optionen in `sed` nutzbar. Folgender Dateiinhalt dient uns nun in der Datei `zitronen.txt` als Ausgangspunkt für unsere Experimente:

Auto-Fahrer fahren Zitronen!
Bier-Brauer brauen Autos.
Zitronen-Falter falten Biere?

Mit einer einfachen Ersetzung lässt sich hier zumindest ein Teil richtigstellen.

user@linux ~ $ sed 's/fahren/essen/' < zitronen.txt
Auto-Fahrer essen Zitronen!
Bier-Brauer brauen Autos.
Zitronen-Falter falten Biere?

Lediglich die Zeichenkette `fahren` passt auf unser Muster und wird daher ersetzt.

Einfache Reguläre Ausdrücke

Fügen wir eine 'Alternative' hinzu, lassen sich immerhin zwei (bei entsprechend vielen Alternativen auch mehr) Zeichenketten gleichzeitig ersetzen. Zu beachten ist hier, dass für `sed` entgegen vielen anderen Implementierung von Regulären Ausdrücken einige Zeichen mit einem Escape-Zeichen, dem Backslash, versehen werden müssen, um ihre spezielle Bedeutung zu erhalten. Genauere Infos dazu gibt die Dokumentation.

user@linux ~ $ sed 's/\(fahren\|brauen\)/interessieren keine/' < zitronen.txt
Auto-Fahrer interessieren keine Zitronen!
Bier-Brauer interessieren keine Autos.
Zitronen-Falter falten Biere?

Aber auch damit geben wir uns nicht zufrieden und hinterfragen die Aussagen erst einmal.

user@linux ~ $ sed 's/\W$/?/' < zitronen.txt
Auto-Fahrer fahren Zitronen?
Bier-Brauer brauen Autos?
Zitronen-Falter falten Biere?

Der Ausdruck `\W` steht für ein Zeichen, das weder Buchstabe noch Zahl noch Unterstrich ist. Das Dollar-Zeichen bezeichnet das Zeilenende. Damit wird das Satzzeichen am Zeilenende durch ein Fragezeichen ersetzt.

Flexible Ersetzung

Aber auch die zu ersetzende Zeichenkette kann sich flexibel verhalten. Das spezielle Zeichen `&` wird durch die komplette Zeichenkette ersetzt, die im Muster trifft.

user@linux ~ $ sed 's/ [a-z]\+ /&keine /' < zitronen.txt
Auto-Fahrer fahren keine Zitronen!
Bier-Brauer brauen keine Autos.
Zitronen-Falter falten keine Biere?

So wird ein Leerzeichen gefolgt von einem oder mehreren kleinen Buchstaben durch selbiges ersetzt, außerdem kommt die Zeichenkette `keine ` hinzu.

Aber auch mit Teilen einer Zeichenkette kann gearbeitet werden. Dazu kopiert `sed` Zeichenketten innerhalb runder Klammern in Zwischenspeichern. Auf diese kann später wieder zurückgegriffen werden, mit Ziffern, denen jeweils ein Backslash vorangestellt wird.

user@linux ~ $ sed 's/\([-A-Za-z]\+\) \([a-z]\+\) \([A-Za-z]\+\)/\3 \2 \1/' < zitronen.txt
Zitronen fahren Auto-Fahrer!
Autos brauen Bier-Brauer.
Biere falten Zitronen-Falter?

So schließen die Klammern jeweils ein Wort ein, die zwischengespeicherten Zeichenketten werden dann rückwärts wieder ausgegeben.

Solche Ausdrücke lassen sich sogar verschachteln.

user@linux ~ $ sed 's/\(\([A-Za-z]\+\).*\) [A-Za-z]\+./\1 \2!/' < zitronen.txt
Auto-Fahrer fahren Auto!
Bier-Brauer brauen Bier!
Zitronen-Falter falten Zitronen!

In diesem Fall ist der zweite Zwischenspeicher, gebildet aus den Buchstaben bis zum Minus, eine Untermenge des ersten. So kommen wir der Wahrheit schon recht nahe.

Der Stream-Editor `sed` bietet noch weitere nützliche Funktionen, die ebenfalls von Regulären Ausdrücken profitieren. Diesen Funktionen wenden wir uns im kommenden Tip des Monats, dem letzten Teil dieser Serie, zu.