Erste Schritte mit Regular Expressions

© Maurus, 123RF

Schnipseljagd

Computer erleichtern die Arbeit – sofern man ihnen genau sagt, was sie tun sollen. Mit regulären Ausdrücken beschleunigen Sie das Suchen und Ersetzen von Zeichenketten auf elegante Art.

README

Der Umgang mit regulären Ausdrücken ähnelt zunächst dem Erlernen und Anwenden einer neuen Sprache. Haben Sie jedoch die einzelnen Symbole und die Grammatik verinnerlicht, meistern Sie auch anspruchsvollere Situationen mit komplizierten Textstrukturen schnell. Dieser Artikel zeigt, wie sich das Konzept der Regular Expressions im Arbeitsalltag bewährt.

Neben dem Übertragen und Darstellen von Daten zählt das Suchen und Ersetzen in Textstrukturen und Zeichenketten zu den häufigsten Aktionen beim Umgang mit dem Computer. Bei letzterem helfen die sogenannten regulären Ausdrücke (engl.: "regular expressions"). Deren Konzept umfasst einen komplexen Text- und Zeichenfilter, der ein ein effektives Suchen und Ersetzen in Zeichenketten jeglicher Form ermöglicht – etwa bei Strings in Programmiersprachen, in Ergebnissen von Datenbankabfragen und in Dokumenten als Dateien auf einem Datenträger.

Es spielt dabei keine Rolle, ob die Textdaten strukturiert vorliegen oder nicht – über Erfolg oder Misserfolg entscheidet nur die richtige Formulierung des regulären Ausdrucks (kurz auch Regex oder RE genannt). Allerdings fällt bei strukturierten Dokumentenformaten wie CSV, HTML, XML, XSLT und LaTeX der Einsatz der REs meist leichter. Das Regex-Konzept ist weit verbreitet und zeichnet sich durch sehr hohe Stabilität aus. Für die Programmiersprachen Java, Perl, Python, PHP, Ruby, das .NET-Framework und für die Linux-Shell Bash gehört es zum Standardumfang.

Die Beschreibung der gesuchten (Zeichen-)Muster folgt bestimmten syntaktischen Regeln, auch Grammatik genannt. Ein Programm wertet diese Grammatik aus und wendet sie auf eine Menge von Zeichen an. Der Rückgabewert umfasst eine Untermenge von Zeichen oder eine Trefferliste. Gibt es keine Übereinstimmung, bleibt diese Liste leer.

Reguläre Ausdrücke formulieren

Bei der Formulierung regulärer Ausdrücke gilt es generell zwei Punkte zu beachten: Erstens hilft es, wenn das Encoding für die Textdaten identisch mit dem des Regex ist. Anderenfalls müssen Sie Umlaute und Sonderzeichen im regulären Ausdruck für das Encoding der Textdaten anpassen. Der zweite Punkt betrifft die Eigenheiten der Regex-Implementierung in der gewählten Programmiersprache: Nicht alle Sprachen unterstützen den POSIX-Standard vollständig und definieren eigene Steuerzeichen.

Grundlagen

Sicherlich haben Sie schon einmal nach einer Person mit einem Namen gesucht, den es in unterschiedlich geschriebenen, aber phonetisch identischen Varianten gibt – etwa nach einem Meier, Schmidt oder Schulze [1]. Die folgenden Beispiele erläutern den Regex-Einsatz anhand dieses Problems. Als Adressbuch dient dabei eine Textdatei, in der Kommas die einzelnen Felder der Einträge trennen (Listing 1). Als Suchwerkzeug für die Kommandozeile kommt grep zum Einsatz.

Listing 1

 

Fritz Neunmalklug, Am Sterndamm 6, 12401 Berlin, 030 24 58 16
Joachim Mayer, 12 Rue de la Chapelle, CH-1002 Lausanne, 0041 21 67 23 69
Hans Fröhlich, Karlplatz 15, 51111 Köln, 0221 76 34 20
Horst Fischer, Rathausquai 78, 20165 Hamburg, 040 30 19 56 1
Klaus Meier, Mozartweg 7, 01256 Dresden, 0351 58 14 17
Holger maier, Kreuzgasse 15, 86161 Augsburg, 0821 50 23 19

Um Herrn Meier im Adressbuch zu finden, geben Sie Grep zwei Parameter mit: den Namen als Suchmuster und unser Adressbuch als Datei, in der Grep nachsehen soll (Listing 2, Zeile 1). Die Ausgabe umfasst nur eine einzige Zeile (Listing 2, Zeile 2).

Falls Sie sich nicht mehr genau daran erinnern können, ob sich der Gesuchte nun Meier oder Mayer schreibt, erweitern Sie den Grep-Aufruf kurzerhand um den passenden regulären Ausdruck (Listing 2, Zeile 4). Mit der Option -E behandelt Grep das Suchmuster als erweiterten Ausdruck und interpretiert die Steuerzeichen entsprechend. Die Klammern um ei gruppieren die beiden Zeichen e und i, der senkrechte Strich (|) fungiert als Oder-Operator für die beiden Gruppen (ei) und (ay). Die zusätzlichen Klammern um (ei)|(ay) sorgen dafür, dass Grep die beiden Gruppen als kompletten Unterausdruck auswertet.

Listing 2

 

$ grep Meier adressbuch
Klaus Meier, Mozartweg 7, 01256 Dresden, 0351 58 14 17
$ grep -E "M((ei)|(ay))er" adressbuch
Joachim Mayer, 12 Rue de la Chapelle, CH-1002 Lausanne, 0041 21 67 23 69
Klaus Meier, Mozartweg 7, 01256 Dresden, 0351 58 14 17
$ grep --color -i -E "M.{2}er" adressbuch
Joachim Mayer, 12 Rue de la Chapelle, CH-1002 Lausanne, 0041 21 67 23 69
Klaus Meier, Mozartweg 7, 01256 Dresden, 0351 58 14 17
Holger maier, Kreuzgasse 15, 86161 Augsburg, 0821 50 23 19

Den dritten Eintrag aus dem Adressbuch (Holger maier) unterschlägt Grep bislang, da der Familienname in der Adressdatei fälschlicherweise mit einem Kleinbuchstaben beginnt. Die Option -i ignoriert die Groß- und Kleinschreibung und fördert auch diesen Eintrag zutage.

Da wir aber auch wissen, dass "Meier" aus fünf Buchstaben besteht, vereinfachen wir den Grep-Aufruf so wie in Zeile 8 von Listing 2. Das Muster M.{2}er passt auf alle Zeichenketten, die mit einem M beginnen, gefolgt von zwei beliebigen, alphanumerischen Zeichen (.{2}) und mit der Buchstabenfolge er am Ende. Welche besonderen Zeichen in einem Muster welche Bedeutung haben, zeigt die Tabelle "Besondere Zeichen in regulären Ausdrücken".

Die Grep-Option --color erweist sich im Alltag als sehr nützlich: Sie hebt diejenigen Zeichen im Suchergebnis hervor, auf die das angegebene Muster passt (Abbildung 1) – in unserem Fall also die passenden Familiennamen.

Abbildung 1: Grep mit farbiger Hervorhebung des Suchergebnisses.

Besondere Zeichen in regulären Ausdrücken

Zeichen

Bedeutung

Beispiel

Treffer bei

?

vorhergehendes Element ist null oder ein Mal vorhanden

(20)?11

2011, 11

+

mindestens eine Wiederholung des vorhergehenden Elements

ab+

ab, abb, abbb, …

*

keine, eine oder mehrere Wiederholungen des vorhergehenden Elements

ab*

a, ab, abb, abbb, …

|

logisches Oder

a|b

a, b

.

beliebiges einzelnes Zeichen

Betr.g

Betrag, Betrug, …

^

am Zeilenanfang

^Berlin

Zeile beginnt mit Berlin

$

Zeilenende

Berlin$

Zeile endet auf Berlin

[...]

Bereich

[a-fA-F]

Zeichen a bis f und A bis F

[^...]

Ausschlussbereich

[^a-f]

alle Zeichen außer a bis f

(...)

gruppiert Elemente

Loch(streifen|karte)

Lochstreifen, Lochkarte

{x,y}

Menge {Minimum, Maximum}

\w{3,8}

mindestens drei und maximal acht alphanumerische Zeichen

\w

alphanumerische Zeichen (a-z, A-Z, 0-9 und _)

\w+; \w+

zwei Worte, durch Semikolon und ein Leerzeichen voneinander getrennt

\s

Leerzeichen (identisch zu \t\n\r\f)

\w+\s+\w+

zwei Worte, durch mindestens ein Leerzeichen oder einen Tabulator getrennt

\d

Ziffern (Grep: [0-9])

Zeile \d

Zeile 0 bis Zeile 9

Um eines der besonderen Zeichen zu finden, müssen Sie es mittels Backslash escapen. Mit \. finden Sie beispielsweise einen Punkt.

Schlangenbeschwörung

Die Programmiersprache Python macht es Ihnen an vielen Stellen sehr leicht. Möchten Sie alle Varianten von Meier aus einer Namensliste herausfischen, dann kodieren Sie das wie in Listing 3 gezeigt. In Zeile 6 wird jeder Eintrag der Namensliste mit den möglichen Varianten verglichen und als Ergebnis lediglich Meier ausgegeben. Zu mayer gibt es keine exakte Entsprechung in der Variantenliste, weswegen Python diesen Eintrag nicht findet.

Listing 3

 

# -*- coding: utf-8 -*-
namensliste = ["Meier", "Müller", "Schulze", "mayer"]
variantenliste = ["Meier", "Meyer", "Maier", "Mayer"]
for eintrag in namensliste:
  if eintrag in variantenliste:
    print(eintrag)

Komfortabler funktioniert das Ganze mithilfe von Funktionen für reguläre Ausdrücke [2]. Diese stellt Python über das Modul re bereit [3] – das Kürzel steht für "regular expressions". Dieses Modul wird in Listing 4 in der dritten Zeile deklariert, ab diesem Punkt lassen sich die Funktionen aus re im Skript nutzen. In Zeile 5 bereitet die Funktion re.compile() das Muster zunächst vor. Dabei steht im Muster [ae] für eines der Zeichen a und e, sinngemäß dasselbe gilt für [iy]. Das Caret (^) benennt den Wortanfang, das Dollarzeichen ($) das Wortende.

Listing 4

 

# -*- coding: utf-8 -*-
import re
namensliste = ["Meier", "Müller", "Schulze", "mayer"]
muster = re.compile('^m[ae][iy]er$', re.IGNORECASE)
for eintrag in namensliste:
  if muster.match(eintrag):
    print(eintrag)

Beim zweiten Parameter des Funktionsaufrufs handelt es sich um re.IGNORECASE, eine vordefinierte Konstante aus dem re-Modul. Sie bewirkt, dass beim Vergleich des Musters die Groß- und Kleinschreibung keine Rolle spielt. Die Funktion re.match() nimmt den Vergleich des Musters mit der Zeichenkette vor. Auf die Namensliste angewendet, erhalten Sie bei der Ausgabe in Zeile 8 sowohl Meier als auch mayer. Diese Variante deckt also alle vier möglichen Schreibweisen ab, ohne sie dazu wie in Listing 3 explizit aufzählen zu müssen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Raspberry Pi Geek kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

Aktuelle Ausgabe

06/2019
Home Improvement

Diese Ausgabe als PDF kaufen

Preis € 9,99
(inkl. 19% MwSt.)

Stellenmarkt

Neuigkeiten

  • Verschlungene Pfade

    Mit Schleifen, Fallunterscheidungen und Funktionen programmieren Sie komplexe Skripte auf einfache und elegante Weise.

  • Extrem genau

    Mit einem A/D-Wandler messen Sie bei Bedarf Spannungen. Der MCP3424 macht dabei konstruktionsbedingt eine gute Figur.

  • Verbindungsaufnahme

  • Süßer Wecker

    Dem RasPi fehlen sowohl eine Echtzeituhr als auch ein BIOS, ein zeitgesteuertes Wecken erfordert also Zusatzkomponenten. Hier springt der Witty Pi Mini in die Bresche, ein µHAT von UUGear.

  • Windows to go

    Das Aufsetzen zuverlässiger und sicherer Remote-Desktop-Lösungen erfordert einiges Know-how. Die RasPi-basierte Pinbox von Pintexx reduziert den Konfigurationsaufwand auf ein Minimum.

  • Prima Klima

    In Museen ist es Pflicht, zu Hause nützlich: das permanente Prüfen und zentrale Erfassen der Feuchtigkeit und Temperatur in Räumen.

  • Auf einen Blick

    Ein maßgeschneiderter Infoscreen auf RasPi-Basis mit stromsparendem E-Ink-Display zeigt Termine, Bilder, Mitteilungen und Wetterinformationen an.

  • Sanft berührt

    Mit einem RasPi und dem Controllermodul PiXtend lassen sich mühelos Roboterarme ansteuern und deren Bewegung automatisieren.

  • Popcorn-Kino

    Mit Kodi 18.0 unterstützt LibreELEC 9.0 jetzt die von vielen Streaming-Diensten genutzte DRM-Verschlüsselung. Die Integration von Netflix, Amazon und Co. erfordert allerdings Handarbeit.

  • So nah und doch so fern

    Der RasPi kommt häufig als Server oder Steuerrechner für spezielle Zwecke zum Einsatz. Mit Anydesk erhalten Sie dazu eine Steuersoftware mit grafischer Oberfläche.