Stellen Sie sich vor, Sie suchen eine Nadel im Heuhaufen. Stellen Sie sich nun vor, Sie haben einen Magneten, der sofort alle Nadeln einer bestimmten Form findet. So funktionieren reguläre Ausdrücke – ein leistungsstarkes Tool zum Suchen und Verarbeiten von Textmustern, das Entwicklern Hunderte von Stunden Routinearbeit erspart.
Was sind reguläre Ausdrücke?
Reguläre Ausdrücke (Regex oder RegEx) sind eine formale Sprache zur Beschreibung von Textmustern. Sie ermöglichen es Ihnen, Text nach komplexen Regeln mithilfe einer kompakten Syntax zu finden, zu extrahieren und zu ersetzen. Anstatt Dutzende von Codezeilen zu schreiben, um eine E-Mail-Adresse zu überprüfen, können Sie einen regulären Ausdruck verwenden.
Reguläre Ausdrücke wurden in den 1950er Jahren vom Mathematiker Stephen Kleene eingeführt, erlangten jedoch mit der Entwicklung von Unix-Systemen und Texteditoren echte Popularität. Heute werden sie in fast allen Programmiersprachen unterstützt.
Grundlegende Syntax
Fangen wir mit dem Einfachen an. Der grundlegendste reguläre Ausdruck ist eine normale Zeichenfolge. Zum Beispiel findet das Muster cat alle Vorkommen des Wortes "cat" im Text. Aber die wahre Stärke von regulären Ausdrücken offenbart sich durch spezielle Zeichen.
Metasymbole sind die Basis von Regex:
. — jedes Zeichen außer Zeilenumbruch. Das Muster c.t findet "cat", "cut", "c9t" und so weiter.
^ — Zeilenanfang. Der Ausdruck ^Hello findet "Hallo" nur am Anfang der Zeile.
$ — Zeilenende. Das Muster world$ findet "world" nur am Ende.
* - Null oder mehr Wiederholungen des vorherigen Zeichens. Zum Beispiel findet go*gle "ggle", "gogle", "google", "goooogle".
+ - eine oder mehrere Wiederholungen. Das Muster go+gle findet "gogle", "google", aber nicht "ggle".
? — Null oder ein Vorkommen. Der Ausdruck colou?r findet sowohl "color" als auch "colour".
[] - Zeichenklasse. Das Muster [aeiou] findet jeden Vokal und [0-9] findet jede Zahl.
| - logisches ODER. Der Ausdruck cat|dog findet entweder "cat" oder "dog".
() — Gruppierung. Mit Klammern können Sie Unterausdrücke erstellen und die gewünschten Textteile erfassen.
Praktische Beispiele
Schauen wir uns die tatsächlichen Herausforderungen an, denen sich Entwickler gegenübersehen.
Validierung der E-Mail-Adresse:
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
return bool(re.match(pattern, email))
print(validate_email("user@example.com")) # True
print(validate_email("invalid.email")) # FalseDieser Ausdruck überprüft die Grundstruktur der E-Mail: Zeichen vor @, Domainname und Zone.
Extraktion von Telefonnummern:
text = "Contacts: +7(999)123-45-67, 8-800-555-35-35"
pattern = r'[\+\d][\d\-\(\)]{9,}'
phones = re.findall(pattern, text)
print(phones) # ['+7(999)123-45-67', '8-800-555-35-35']Ersetzen sensibler Daten:
text = "My card number: 1234-5678-9012-3456"
pattern = r'\d{4}-\d{4}-\d{4}-\d{4}'
masked = re.sub(pattern, '****-****-****-****', text)
print(masked) # Meine Kartennummer: **** - **** - **** - ****URL-Parsing:
url = "https://example.com:8080/path/to/page?param=value#section"
pattern = r'(?P<protocol>https?://)?(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/[^?#]*)?(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?'
match = re.match(pattern, url)
print(match.group('domain')) # example.com
print(match.group('port')) # 8080Fortgeschrittene Techniken
Lookahead und Lookbehind — sind leistungsstarke Tools für die kontextuelle Suche ohne Text-Capture.
Positiver Lookahead (?=...) - prüft, ob ein bestimmtes Muster folgt:
# Finden Sie Wörter, die mit einem Ausrufezeichen enden
pattern = r'\w+(?=!)'
text = "Hi! How are you? Great!"
print(re.findall(pattern, text)) # ['Hallo', 'Ausgezeichnet']]Negativer Lookahead (?!...) - überprüft, ob das Muster NICHT weitergeht:
# Finden Sie die Zahlen, denen kein Rubelzeichen folgt
pattern = r'\d+(?!₽)'
text = "100₽, 200, 300₽, 400"
print(re.findall(pattern, text)) # ['200', '400']Gierige und faule Quantifikatoren:
Standardmäßig sind Quantifikatoren gierig - sie erfassen ein Maximum an Text:
text = "<div>First</div><div>Second</div>"
pattern = r'<div>.*</div>'
print(re.findall(pattern, text))
# ['<div>Erster</div><div>Zweiter</div>'] # Alles erfasst!Durch Hinzufügen von ? machen wir den Quantifikator träge:
pattern = r'<div>.*?</div>'
print(re.findall(pattern, text))
# ['<div>Erster</div>', '<div>Zweiter</div>'] # Zwei separate ÜbereinstimmungenBenannte Gruppen machen den Code lesbar:
log = "2024-11-25 14:30:15 ERROR Database connection failed"
pattern = r'(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2}) (?P<level>\w+) (?P<message>.*)'
match = re.match(pattern, log)
print(match.group('level')) # ERROR
print(match.group('message')) # Database connection failed
Leistung und Optimierung
Reguläre Ausdrücke können bei falscher Verwendung langsam sein. Hier sind einige Tipps:
Kompilieren Sie Muster zur Wiederverwendung:
# Schlecht - wird jedes Mal kompiliert
for text in texts:
if re.match(r'\d{3}-\d{3}', text):
process(text)
# Gut - wird einmal kompiliert
pattern = re.compile(r'\d{3}-\d{3}')
for text in texts:
if pattern.match(text):
process(text)Vermeiden Sie katastrophales Backtracking:
Einige Muster können zu einem exponentiellen Anstieg der Ausführungszeit führen:
# Gefährlich!
pattern = r'(a+)+'
text = "aaaaaaaaaaaaaaaaaaaaaaaX" # Kann hängen bleibenDies ist auf mehrere Zuordnungswege bei Fehlern zurückzuführen. Die Lösung besteht darin, atomare Gruppen oder possessive Quantifikatoren zu verwenden, sofern diese unterstützt werden.
Verwenden Sie Anker:
# Langsamer
pattern = r'\d{4}-\d{2}-\d{2}'
# Schneller, wenn das Datum am Anfang der Zeile steht
pattern = r'^\d{4}-\d{2}-\d{2}'Debuggen von regulären Ausdrücken
Regex kann schwer zu verstehen sein. Verwenden Sie Visualisierungs- und Testwerkzeuge:
regex101.com — ein hervorragendes Online-Tool mit Erläuterungen
debuggex.com — Visualisierung von Mustern in Form von Diagrammen
regexr.com - interaktive Sandbox mit Hinweisen
Für komplexe Ausdrücke fügen Sie Kommentare mit dem Flag re.VERBOSE hinzu:
pattern = re.compile(r'''
^ # Start of line
(?P<username> # Group for username
[a-zA-Z0-9_]{3,16} # From 3 to 16 alphanumeric characters
)
@ # Symbol @
(?P<domain> # Group for domain
[a-zA-Z0-9.-]+ # Domain name
\.[a-zA-Z]{2,} # Point and zone
)
$ # End of line
'OSE)Alternativen zu regulären Ausdrücken
Regex ist nicht immer die beste Lösung. Für einige Aufgaben ist es besser, spezielle Tools zu verwenden:
Verwenden Sie zum Parsen von HTML BeautifulSoup oder lxml anstelle von regex - HTML ist keine reguläre Sprache und regex kann zu unvorhersehbaren Ergebnissen führen.
Verwenden Sie zum Parsen von JSON die integrierten Bibliotheken. Für komplexe Grammatiken sollten Parser-Generatoren wie PLY oder ANTLR in Betracht gezogen werden.
Für eine einfache Suche nach Teilzeichenfolgen sind Zeichenfolgenmethoden oft schneller und verständlicher als reguläre Ausdrücke.
Befund
Reguläre Ausdrücke sind ein mächtiges Werkzeug im Arsenal eines Entwicklers. Sie sparen Zeit, machen den Code kompakt und lösen Probleme, die sonst Dutzende von Codezeilen erfordern würden. Beginnen Sie mit einfachen Mustern, üben Sie an echten Aufgaben, und allmählich werden Sie diese Mustersprache beherrschen. Denken Sie an die Leistung, verwenden Sie Debugging-Tools und scheuen Sie sich nicht, zu experimentieren. Im Laufe der Zeit werden reguläre Ausdrücke zu einem natürlichen Bestandteil Ihres Arbeitsablaufs.
Möchten Sie mehr über Programmierung erfahren und lernen, wie man Tools wie reguläre Ausdrücke in der Praxis anwendet? Die Anwendung Kodik bietet strukturierte Kurse in Python, JavaScript und Webentwicklung für Einsteiger an. Schließen Sie sich unserem Telegram-Kanal, wo Sie nützliche Materialien, Analysen komplexer Themen und Unterstützung durch eine Gemeinschaft von Gleichgesinnten finden, die bereit sind, Ihnen auf Ihrem Weg in die Programmierung zu helfen.
