Python - Regular Expressions (Deutsch)

Hallo da, zukünftige Python-Zauberer! Heute werden wir auf eine aufregende Reise in die Welt der regulären Ausdrücke (regex) in Python aufbrechen. Keine Sorge, wenn du noch nie von regex gehört hast – am Ende dieses Tutorials wirst du diese mächtige Werkzeug wie ein Profi führen!

Python - Reg Expressions

Was sind Regular Expressions?

Bevor wir einsteigen, lassen uns verstehen, was reguläre Ausdrücke sind. Stell dir vor, du bist ein Detektiv, der versucht, ein bestimmtes Muster in einem Meer aus Text zu finden. Reguläre Ausdrücke sind wie dein Lupen, der dir hilft, nach Zeichenketten basierend auf Mustern zu suchen und zu manipulieren. Cool, nicht wahr?

Raw Strings

In Python verwenden wir bei der Arbeit mit regex oft Raw Strings. Diese sind mit einem 'r' prefixiert und behandeln Backslashes als literale Zeichen. Dies ist besonders nützlich in regex, da Backslashes häufig vorkommen.

# Normale Zeichenkette
print("Hallo\nWelt")
# Raw String
print(r"Hallo\nWelt")

Im ersten Fall wirst du "Hallo" und "Welt" in separaten Zeilen sehen. Im zweiten Fall wirst du "Hallo\nWelt" so wie es ist sehen. Dies wird entscheidend, wenn du mit regex-Mustern arbeitest.

Metacharaktere

Metacharaktere sind die Bausteine von regex. Sie haben spezielle Bedeutungen und helfen uns, Muster zu definieren. Lass uns einige gängige anschauen:

Metacharakter Bedeutung
. Stimmt mit jedem Zeichen außer Zeilenumbruch überein
^ Stimmt mit dem Anfang einer Zeichenkette überein
$ Stimmt mit dem Ende einer Zeichenkette überein
* Stimmt mit 0 oder mehr Wiederholungen überein
+ Stimmt mit 1 oder mehr Wiederholungen überein
? Stimmt mit 0 oder 1 Wiederholung überein
{} Stimmt mit einer explizit angegebenen Anzahl von Wiederholungen überein
[] Gibt eine Menge von Zeichen zum Stimmen an
\ Maskiert Sonderzeichen

Die re.match() Funktion

Die re.match()-Funktion versucht, ein Muster am Anfang einer Zeichenkette zu stimmen. Wenn sie ein Übereinstimmendes findet, gibt sie ein Übereinstimmungsobjekt zurück; andernfalls gibt sie None zurück.

import re

ergebnis = re.match(r"Hallo", "Hallo, Welt!")
if ergebnis:
print("Treffer gefunden:", ergebnis.group())
else:
print("Kein Treffer")

Dies wird "Treffer gefunden: Hallo" ausgeben. Die group()-Methode gibt den übereinstimmenden Teilstring zurück.

Die re.search() Funktion

Während re.match() am Anfang einer Zeichenkette nach einem Treffer sucht, durchsucht re.search() die gesamte Zeichenkette nach einem Treffer.

import re

ergebnis = re.search(r"Welt", "Hallo, Welt!")
if ergebnis:
print("Treffer gefunden:", ergebnis.group())
else:
print("Kein Treffer")

Dies wird "Treffer gefunden: Welt" ausgeben.

Vergleich von match() und search()

Der Hauptunterschied zwischen match() und search() ist, dass match() nur am Anfang der Zeichenkette nach einem Treffer sucht, während search() überall in der Zeichenkette nach einem Treffer sucht.

Die re.findall() Funktion

Die re.findall()-Funktion gibt alle nicht überlappenden Treffer eines Musters in einer Zeichenkette als Liste zurück.

import re

text = "Der Regen in Spanien fällt hauptsächlich in die Ebene"
ergebnis = re.findall(r"ain", text)
print(ergebnis)

Dies wird ['ain', 'ain', 'ain'] ausgeben.

Die re.sub() Funktion

Die re.sub()-Funktion ersetzt alle Vorkommen eines Musters in einer Zeichenkette durch eine Ersatzzeichenkette.

import re

text = "Der Regen in Spanien"
ergebnis = re.sub(r"a", "o", text)
print(ergebnis)

Dies wird "Der Roegen in Spoin" ausgeben.

Die re.compile() Funktion

Die re.compile()-Funktion erstellt ein regex-Objekt zur Wiederverwendung, was effizienter sein kann, wenn du das gleiche Muster mehrmals verwendest.

import re

muster = re.compile(r"\d+")
ergebnis1 = muster.findall("Es gibt 123 Äpfel und 456 Orangen")
ergebnis2 = muster.findall("Ich habe 789 Bananen")

print(ergebnis1)
print(ergebnis2)

Dies wird ['123', '456'] und ['789'] ausgeben.

Die re.finditer() Funktion

Die re.finditer()-Funktion gibt einen Iterator zurück, der Übereinstimmungsobjekte für alle nicht überlappenden Treffer eines Musters in einer Zeichenkette liefert.

import re

text = "Der Regen in Spanien"
for treffer in re.finditer(r"ain", text):
print(f"Gefunden '{treffer.group()}' an Position {treffer.start()}-{treffer.end()}")

Dies wird ausgeben:

Gefunden 'ain' an Position 5-8
Gefunden 'ain' an Position 17-20

Anwendungsfälle von Python Regex

Reguläre Ausdrücke haben zahlreiche praktische Anwendungen. Lass uns einen gängigen Anwendungsfall anschauen:

Finden von Wörtern, die mit Vokalen beginnen

import re

text = "Ein Apfel am Tag hält den Arzt fern"
vokal_wörter = re.findall(r'\b[aeiouAEIOU]\w+', text)
print(vokal_wörter)

Dies wird ['Ein', 'Apfel', 'a', 'fern'] ausgeben.

Regular Expression Modifikatoren: Optionsschalter

Pythons re-Modul bietet mehrere Optionsschalter an, die beeinflussen, wie Muster interpretiert werden:

Schalter Beschreibung
re.IGNORECASE (re.I) Führt eine Groß- und Kleinschreibung ignorierende Übereinstimmung durch
re.MULTILINE (re.M) Macht ^ am Anfang jeder Zeile und $ am Ende jeder Zeile übereinstimmen
re.DOTALL (re.S) Macht . mit jedem Zeichen, einschließlich Zeilenumbruch, übereinstimmen
re.VERBOSE (re.X) Ermöglicht es dir, lesbarere regex-Muster zu schreiben

Regular Expression Patterns

Lass uns einige fortgeschrittene Muster erkunden:

Zeichenklassen

Zeichenklassen ermöglichen es dir, eine Menge von Zeichen zum Stimmen an zu geben:

import re

text = "Der schnelle braune Fuchs springt über den faulen Hund"
ergebnis = re.findall(r"[aeiou]", text)
print(ergebnis)

Dies wird alle Vokale im Text ausgeben.

Spezielle Zeichenklassen

Python regex unterstützt spezielle Zeichenklassen:

Klasse Beschreibung
\d Stimmt mit jeder dezimalen Ziffer überein
\D Stimmt mit jedem nichtnumerischen Zeichen überein
\s Stimmt mit jedem Leerzeichenzeichen überein
\S Stimmt mit jedem nichtleeren Zeichen überein
\w Stimmt mit jedem alphanumerischen Zeichen überein
\W Stimmt mit jedem nichtalphanumerischen Zeichen überein

Wiederholungsfälle

Wir können angeben, wie oft ein Muster auftreten soll:

import re

text = "Ich habe 111 Äpfel und 22 Orangen"
ergebnis = re.findall(r"\d{2,3}", text)
print(ergebnis)

Dies wird ['111', '22'] ausgeben, stimmt mit Zahlen mit 2 oder 3 Ziffern überein.

Nongreedy-Wiederholung

Standardmäßig ist die Wiederholung gierig, was bedeutet, dass sie so viel wie möglich übereinstimmt. Das Hinzufügen eines ? nach der Wiederholung macht sie non-greedy:

import re

text = "<h1>Titel</h1><p>Paragraph</p>"
gierig = re.findall(r"<.*>", text)
non_gierig = re.findall(r"<.*?>", text)
print("Gierig:", gierig)
print("Non-gierig:", non_gierig)

Dies wird den Unterschied zwischen gieriger und non-gieriger Übereinstimmung zeigen.

Gruppierung mit Klammern

Klammern ermöglichen es dir, Teile des regex zu gruppieren:

import re

text = "John Smith ([email protected])"
ergebnis = re.search(r"(\w+) (\w+) \((\w+@\w+\.\w+)\)", text)
if ergebnis:
print(f"Voller Name: {ergebnis.group(1)} {ergebnis.group(2)}")
print(f"Email: {ergebnis.group(3)}")

Dies extrahiert den Namen und die E-Mail aus dem Text.

Rückverweise

Rückverweise ermöglichen es dir, auf zuvor übereinstimmende Gruppen zu verweisen:

import re

text = "<h1>Titel</h1><p>Paragraph</p>"
ergebnis = re.findall(r"<(\w+)>.*?</\1>", text)
print(ergebnis)

Dies stimmt mit öffnenden und schließenden HTML-Tags überein.

Alternativen

Das | Zeichen ermöglicht es dir, Alternativen anzugeben:

import re

text = "Die Farbe des Himmels ist blau oder grau"
ergebnis = re.search(r"blau|grau", text)
if ergebnis:
print(f"Gefundene Farbe: {ergebnis.group()}")

Dies stimmt entweder mit "blau" oder "grau" überein.

Anker

Anker geben Positionen im Text an:

import re

text = "Python ist großartig"
start = re.match(r"^Python", text)
end = re.search(r"grossartig$", text)
print(f"Beginnt mit Python: {bool(start)}")
print(f"Endet mit grossartig: {bool(end)}")

Dies überprüft, ob der Text mit "Python" beginnt und mit "großartig" endet.

Spezielle Syntax mit Klammern

Klammern können für mehr als nur Gruppierung verwendet werden:

  • (?:...) erstellt eine nicht erfasende Gruppe
  • (?P...) erstellt eine benannte Gruppe
  • (?=...) erstellt einen positiven Ausblick
  • (?!...) erstellt einen negativen Ausblick
import re

text = "Python Version 3.9.5"
ergebnis = re.search(r"Python (?:Version )?(?P<version>\d+\.\d+\.\d+)", text)
if ergebnis:
print(f"Version: {ergebnis.group('version')}")

Dies extrahiert die Versionsnummer, obwohl "Version" im Text vorhanden sein mag oder nicht.

Und da haben wir es, Freunde! Wir haben durch die Welt der Python regex gereist, von den Grundlagen bis zu einige ziemlich fortgeschrittene Konzepte. Bedenke, wie jedes mächtige Werkzeug, nimmt es Praxis, um regex zu meistern. Also lass dich nicht entmutigen, wenn es am Anfang überwältigend erscheint. Führe weiterhin Experimente durch, und bald wirst du wie ein Profi-Detektiv Muster finden! Glückliches Coden!

Credits: Image by storyset