HOWTO zu regulären Ausdrücken
*****************************


Zusammenfassung
^^^^^^^^^^^^^^^

Dieses Dokument ist eine einführende Anleitung zum Umgang mit
regulären Ausdrücken in Python mit dem Modul "re".  Es führt
behutsamer ein als der entsprechende Abschnitt in der
Bibliotheksreferenz.


Einführung
==========

Reguläre Ausdrücke (kurz REs, Regexes oder Regex-Muster) sind im Kern
eine kleine, hochspezialisierte Programmiersprache, die in Python
eingebettet ist und über das Modul "re" bereitsteht. Mit dieser
kleinen Sprache gibst du die Regeln für die Menge der möglichen
Zeichenketten an, auf die du passen willst. Diese Menge kann englische
Sätze, E-Mail-Adressen, TeX-Befehle oder beliebiges anderes enthalten.
Anschließend kannst du Fragen stellen wie „Passt diese Zeichenkette
auf das Muster?“ oder „Gibt es irgendwo in dieser Zeichenkette eine
Fundstelle für das Muster?“.  Du kannst REs auch verwenden, um eine
Zeichenkette zu verändern oder auf verschiedene Weisen zu zerlegen.

Muster regulärer Ausdrücke werden in eine Folge von Bytecodes
übersetzt, die dann von einer in C geschriebenen Suchmaschine
ausgeführt werden.  Für fortgeschrittene Zwecke kann es nötig sein,
genau darauf zu achten, wie die Maschine einen bestimmten RE ausführt,
und den RE so zu schreiben, dass schnellerer Bytecode entsteht.
Optimierung behandelt dieses Dokument nicht, weil sie ein gutes
Verständnis der Interna der Suchmaschine voraussetzt.

Die Sprache der regulären Ausdrücke ist relativ klein und
eingeschränkt, deshalb lassen sich nicht alle denkbaren Aufgaben der
Zeichenkettenverarbeitung mit regulären Ausdrücken lösen.  Es gibt
außerdem Aufgaben, die sich mit regulären Ausdrücken lösen *lassen*,
bei denen die Ausdrücke aber sehr kompliziert werden.  In diesen
Fällen fährst du möglicherweise besser damit, die Verarbeitung in
Python-Code zu schreiben; Python-Code ist zwar langsamer als ein
ausgefeilter regulärer Ausdruck, dafür aber wahrscheinlich
verständlicher.


Einfache Muster
===============

Wir fangen mit den einfachsten möglichen regulären Ausdrücken an.  Da
reguläre Ausdrücke auf Zeichenketten angewendet werden, beginnen wir
mit der häufigsten Aufgabe: dem Passen auf Zeichen.

Eine ausführliche Erklärung der informatischen Grundlagen regulärer
Ausdrücke (deterministische und nichtdeterministische endliche
Automaten) findest du in nahezu jedem Lehrbuch über das Schreiben von
Compilern.


Auf Zeichen passen
------------------

Die meisten Buchstaben und Zeichen passen einfach auf sich selbst.
Der reguläre Ausdruck "test" passt zum Beispiel genau auf die
Zeichenkette "test".  (Du kannst einen Modus einschalten, der Groß-
und Kleinschreibung ignoriert und bei dem dieser RE auch auf "Test"
oder "TEST" passt. Dazu später mehr.)

Von dieser Regel gibt es Ausnahmen. Manche Zeichen sind besondere
*Metazeichen* und passen nicht auf sich selbst.  Stattdessen zeigen
sie an, dass etwas Außergewöhnliches passen soll, oder sie
beeinflussen andere Teile des RE, indem sie sie wiederholen oder ihre
Bedeutung ändern.  Ein großer Teil dieses Dokuments widmet sich den
verschiedenen Metazeichen und ihrer Wirkung.

Hier eine vollständige Liste der Metazeichen. Ihre Bedeutungen werden
im weiteren Verlauf dieses HOWTO besprochen.

   . ^ $ * + ? { } [ ] \ | ( )

Die ersten Metazeichen, die wir uns ansehen, sind "[" und "]". Mit
ihnen gibst du eine Zeichenklasse an, also eine Menge von Zeichen, auf
die du passen willst.  Die Zeichen lassen sich einzeln aufführen, oder
du gibst einen Zeichenbereich an, indem du zwei Zeichen durch ein
"'-'" trennst. "[abc]" passt zum Beispiel auf jedes der Zeichen "a",
"b" oder "c". Das ist dasselbe wie "[a-c]", das dieselbe Zeichenmenge
über einen Bereich ausdrückt.  Willst du nur auf Kleinbuchstaben
passen, lautet dein RE "[a-z]".

Metazeichen (außer "\") sind innerhalb von Klassen nicht aktiv.
"[akm$]" passt zum Beispiel auf jedes der Zeichen "'a'", "'k'", "'m'"
oder "'$'"; "'$'" ist normalerweise ein Metazeichen, innerhalb einer
Zeichenklasse verliert es aber seine besondere Bedeutung.

Du kannst auf die Zeichen passen, die *nicht* in der Klasse aufgeführt
sind, indem du die Menge *komplementierst*.  Dazu nimmst du ein "'^'"
als erstes Zeichen der Klasse. "[^5]" passt zum Beispiel auf jedes
Zeichen außer "'5'".  Steht das Caret an anderer Stelle in einer
Zeichenklasse, hat es keine besondere Bedeutung. Beispiel: "[5^]"
passt entweder auf eine "'5'" oder auf ein "'^'".

Das vielleicht wichtigste Metazeichen ist der Backslash, "\".   Wie in
Python-Zeichenkettenliteralen kann auf den Backslash eine Reihe
verschiedener Zeichen folgen, die verschiedene besondere Sequenzen
anzeigen. Er dient außerdem dazu, alle Metazeichen zu maskieren, damit
du in Mustern weiterhin auf sie passen kannst. Musst du zum Beispiel
auf ein "[" oder "\" passen, kannst du einen Backslash davorsetzen, um
ihre besondere Bedeutung zu entfernen: "\[" oder "\\".

Einige der besonderen Sequenzen, die mit "'\'" beginnen, stehen für
vordefinierte Zeichenmengen, die oft nützlich sind, etwa die Menge der
Ziffern, die Menge der Buchstaben oder die Menge all dessen, was kein
Leerraum ist.

Nehmen wir ein Beispiel: "\w" passt auf jedes alphanumerische Zeichen.
Ist das Regex-Muster als Bytes ausgedrückt, entspricht das der Klasse
"[a-zA-Z0-9_]".  Ist das Regex-Muster eine Zeichenkette, passt "\w"
auf alle Zeichen, die in der Unicode-Datenbank des Moduls
"unicodedata" als Buchstaben markiert sind.  Die stärker
eingeschränkte Bedeutung von "\w" kannst du in einem
Zeichenkettenmuster erreichen, indem du beim Übersetzen des regulären
Ausdrucks das Flag "re.ASCII" angibst.

Die folgende Liste besonderer Sequenzen ist nicht vollständig. Eine
vollständige Liste der Sequenzen und die erweiterten
Klassendefinitionen für Unicode-Zeichenkettenmuster findest du im
letzten Teil von Syntax regulärer Ausdrücke in der Referenz der
Standardbibliothek. Allgemein passen die Unicode-Varianten auf jedes
Zeichen, das in der Unicode-Datenbank zur passenden Kategorie gehört.

"\d"
   Passt auf jede Dezimalziffer. Das entspricht der Klasse "[0-9]".

"\D"
   Passt auf jedes Zeichen, das keine Ziffer ist. Das entspricht der
   Klasse "[^0-9]".

"\s"
   Passt auf jedes Leerraumzeichen. Das entspricht der Klasse "[
   \t\n\r\f\v]".

"\S"
   Passt auf jedes Zeichen, das kein Leerraum ist. Das entspricht der
   Klasse "[^ \t\n\r\f\v]".

"\w"
   Passt auf jedes alphanumerische Zeichen. Das entspricht der Klasse
   "[a-zA-Z0-9_]".

"\W"
   Passt auf jedes Zeichen, das nicht alphanumerisch ist. Das
   entspricht der Klasse "[^a-zA-Z0-9_]".

Diese Sequenzen lassen sich in eine Zeichenklasse aufnehmen.  "[\s,.]"
ist zum Beispiel eine Zeichenklasse, die auf jedes Leerraumzeichen
sowie auf "','" oder "'.'" passt.

Das letzte Metazeichen in diesem Abschnitt ist ".".  Es passt auf
alles außer einem Zeilenumbruchzeichen, und es gibt einen abweichenden
Modus ("re.DOTALL"), in dem es sogar auf einen Zeilenumbruch passt.
"." wird oft dort verwendet, wo man auf „ein beliebiges Zeichen“
passen will.


Dinge wiederholen
-----------------

Auf unterschiedliche Zeichenmengen passen zu können, ist das Erste,
was reguläre Ausdrücke leisten und was mit den Methoden von
Zeichenketten nicht schon möglich wäre.  Wäre das allerdings die
einzige zusätzliche Fähigkeit von Regexes, wären sie kein großer
Fortschritt. Eine weitere Fähigkeit ist, dass du angeben kannst, dass
Teile des RE eine bestimmte Anzahl von Malen wiederholt werden müssen.

Das erste Metazeichen zum Wiederholen, das wir uns ansehen, ist "*".
"*" passt nicht auf das wörtliche Zeichen "'*'". Es gibt stattdessen
an, dass das vorangehende Zeichen null oder mehr Mal passen darf statt
genau einmal.

"ca*t" passt zum Beispiel auf "'ct'" (0 Zeichen "'a'"), "'cat'" (1
"'a'"), "'caaat'" (3 Zeichen "'a'") und so weiter.

Wiederholungen wie "*" sind *gierig*. Beim Wiederholen eines RE
versucht die Suchmaschine, ihn so oft wie möglich zu wiederholen.
Passen spätere Teile des Musters dann nicht, geht die Suchmaschine
zurück und versucht es erneut mit weniger Wiederholungen.

Ein Beispiel Schritt für Schritt macht das deutlicher.  Betrachten wir
den Ausdruck "a[bcd]*b".  Er passt auf den Buchstaben "'a'", null oder
mehr Buchstaben aus der Klasse "[bcd]" und schließt schließlich mit
einem "'b'" ab.  Stell dir nun vor, dieser RE wird gegen die
Zeichenkette "'abcbd'" geprüft.

+--------+-------------+-----------------------------------+
| Schri  | Gefunden    | Erklärung                         |
| tt     |             |                                   |
|========|=============|===================================|
| 1      | "a"         | Das "a" im RE passt.              |
+--------+-------------+-----------------------------------+
| 2      | "abcbd"     | Die Maschine lässt "[bcd]*"       |
|        |             | passen und geht dabei so weit wie |
|        |             | möglich, also bis zum Ende der    |
|        |             | Zeichenkette.                     |
+--------+-------------+-----------------------------------+
| 3      | *Fehlschla  | Die Maschine versucht, "b" passen |
|        | g*          | zu lassen, aber die aktuelle      |
|        |             | Position liegt am Ende der        |
|        |             | Zeichenkette, also schlägt es     |
|        |             | fehl.                             |
+--------+-------------+-----------------------------------+
| 4      | "abcb"      | Zurückgehen, sodass  "[bcd]*" auf |
|        |             | ein Zeichen weniger passt.        |
+--------+-------------+-----------------------------------+
| 5      | *Fehlschla  | "b" erneut versuchen, aber die    |
|        | g*          | aktuelle Position liegt beim      |
|        |             | letzten Zeichen, und das ist ein  |
|        |             | "'d'".                            |
+--------+-------------+-----------------------------------+
| 6      | "abc"       | Erneut zurückgehen, sodass        |
|        |             | "[bcd]*" nur noch auf "bc" passt. |
+--------+-------------+-----------------------------------+
| 7      | "abcb"      | "b" erneut versuchen.  Diesmal    |
|        |             | ist das Zeichen an der aktuellen  |
|        |             | Position ein "'b'", also gelingt  |
|        |             | es.                               |
+--------+-------------+-----------------------------------+

Das Ende des RE ist nun erreicht, und er hat auf "'abcb'" gepasst.
Das zeigt, wie die Suchmaschine zuerst so weit geht, wie sie kann, und
dann, wenn keine Fundstelle zustande kommt, schrittweise zurückgeht
und den restlichen RE immer wieder neu versucht.  Sie geht zurück, bis
sie null Fundstellen für "[bcd]*" versucht hat, und schließt, wenn
auch das fehlschlägt, dass die Zeichenkette überhaupt nicht auf den RE
passt.

Ein weiteres Metazeichen zum Wiederholen ist "+", das ein oder mehr
Mal passt.  Achte genau auf den Unterschied zwischen "*" und "+"; "*"
passt *null* oder mehr Mal, das Wiederholte muss also gar nicht
vorhanden sein, während "+" mindestens *ein* Vorkommen verlangt.  Um
beim ähnlichen Beispiel zu bleiben: "ca+t" passt auf "'cat'" (1 "'a'")
und "'caaat'" (3 "'a'"s), aber nicht auf "'ct'".

Es gibt zwei weitere Wiederholungsoperatoren oder Quantoren.  Das
Fragezeichen, "?", passt entweder einmal oder null Mal. Du kannst es
als Markierung dafür verstehen, dass etwas optional ist.  "home-?brew"
passt zum Beispiel entweder auf "'homebrew'" oder auf "'home-brew'".

Der komplizierteste Quantor ist "{m,n}", wobei *m* und *n*
Dezimalzahlen sind.  Dieser Quantor bedeutet, dass es mindestens *m*
und höchstens *n* Wiederholungen geben muss.  "a/{1,3}b" passt zum
Beispiel auf "'a/b'", "'a//b'" und "'a///b'".  Es passt nicht auf
"'ab'", das keine Schrägstriche hat, und nicht auf "'a////b'", das
vier hat.

Du kannst entweder *m* oder *n* weglassen. In diesem Fall wird für den
fehlenden Wert ein sinnvoller Wert angenommen.  Ein fehlendes *m* wird
als Untergrenze 0 verstanden, ein fehlendes *n* führt zu einer
Obergrenze von unendlich.

Der einfachste Fall "{m}" passt genau *m* Mal auf das vorangehende
Element. "a/{2}b" passt zum Beispiel nur auf "'a//b'".

Wer zur Reduktion neigt, merkt vielleicht, dass sich die drei anderen
Quantoren alle mit dieser Schreibweise ausdrücken lassen.  "{0,}" ist
dasselbe wie "*", "{1,}" entspricht "+", und "{0,1}" ist dasselbe wie
"?".  Es ist besser, "*", "+" oder "?" zu verwenden, wo es möglich
ist, einfach weil sie kürzer und leichter zu lesen sind.


Reguläre Ausdrücke verwenden
============================

Nachdem wir uns einige einfache reguläre Ausdrücke angesehen haben:
Wie verwendet man sie nun tatsächlich in Python?  Das Modul "re"
bietet eine Schnittstelle zur Maschine für reguläre Ausdrücke, mit der
du REs zu Objekten übersetzen und damit dann Suchen durchführen
kannst.


Reguläre Ausdrücke übersetzen
-----------------------------

Reguläre Ausdrücke werden zu Musterobjekten übersetzt, die Methoden
für verschiedene Operationen besitzen, etwa das Suchen nach
Fundstellen eines Musters oder das Ersetzen in Zeichenketten.

   >>> import re
   >>> p = re.compile('ab*')
   >>> p
   re.compile('ab*')

"re.compile()" nimmt außerdem ein optionales Argument *flags*, mit dem
sich verschiedene besondere Eigenschaften und Syntaxvarianten
einschalten lassen.  Die verfügbaren Einstellungen gehen wir später
durch, für den Moment genügt ein einzelnes Beispiel:

   >>> p = re.compile('ab*', re.IGNORECASE)

Der RE wird "re.compile()" als Zeichenkette übergeben.  REs werden als
Zeichenketten behandelt, weil reguläre Ausdrücke nicht Teil der
Kernsprache Python sind und keine besondere Syntax für ihre
Formulierung geschaffen wurde.  (Es gibt Anwendungen, die überhaupt
keine REs brauchen, also gibt es keinen Grund, die Sprachspezifikation
damit aufzublähen.) Das Modul "re" ist stattdessen einfach ein
C-Erweiterungsmodul, das mit Python ausgeliefert wird, genau wie die
Module "socket" oder "zlib".

REs in Zeichenketten zu stecken hält die Sprache Python einfacher, hat
aber einen Nachteil, der Thema des nächsten Abschnitts ist.


Die Backslash-Plage
-------------------

Wie bereits erwähnt, verwenden reguläre Ausdrücke das Backslash-
Zeichen ("'\'"), um besondere Formen anzuzeigen oder besondere Zeichen
ohne ihre besondere Bedeutung verwendbar zu machen. Das kollidiert
damit, dass Python dasselbe Zeichen zu demselben Zweck in
Zeichenkettenliteralen verwendet.

Nehmen wir an, du willst einen RE schreiben, der auf die Zeichenkette
"\section" passt, wie sie in einer LaTeX-Datei vorkommen kann.  Um
herauszufinden, was im Programmcode stehen muss, fang mit der
gewünschten Zeichenkette an, auf die gepasst werden soll.  Als
Nächstes musst du alle Backslashes und anderen Metazeichen maskieren,
indem du einen Backslash davorsetzt. Das ergibt die Zeichenkette
"\\section".  Die daraus entstehende Zeichenkette, die an
"re.compile()" übergeben werden muss, lautet also "\\section".  Um das
jedoch als Python-Zeichenkettenliteral auszudrücken, müssen beide
Backslashes *noch einmal* maskiert werden.

+---------------------+--------------------------------------------+
| Zeichen             | Stufe                                      |
|=====================|============================================|
| "\section"          | Textzeichenkette, auf die gepasst werden   |
|                     | soll                                       |
+---------------------+--------------------------------------------+
| "\\section"         | Maskierter Backslash für "re.compile()"    |
+---------------------+--------------------------------------------+
| ""\\\\section""     | Maskierte Backslashes für ein              |
|                     | Zeichenkettenliteral                       |
+---------------------+--------------------------------------------+

Kurz gesagt: Um auf einen wörtlichen Backslash zu passen, muss man
"'\\\\'" als RE-Zeichenkette schreiben, denn der reguläre Ausdruck
muss "\\" lauten, und jeder Backslash muss innerhalb eines
gewöhnlichen Python-Zeichenkettenliterals als "\\" ausgedrückt werden.
In REs, in denen Backslashes immer wieder vorkommen, führt das zu
einer Menge wiederholter Backslashes und macht die entstehenden
Zeichenketten schwer verständlich.

Die Lösung besteht darin, für reguläre Ausdrücke Pythons Raw-String-
Schreibweise zu verwenden. In einem Zeichenkettenliteral mit dem
Präfix "'r'" werden Backslashes nicht besonders behandelt, "r"\n"" ist
also eine Zeichenkette aus zwei Zeichen, die "'\'" und "'n'" enthält,
während ""\n"" eine Zeichenkette aus einem Zeichen ist, die einen
Zeilenumbruch enthält. Reguläre Ausdrücke werden in Python-Code häufig
in dieser Raw-String-Schreibweise geschrieben.

Darüber hinaus führen besondere Escape-Sequenzen, die in regulären
Ausdrücken gültig sind, als Python-Zeichenkettenliterale aber nicht,
jetzt zu einer "SyntaxWarning" und werden später zu einem
"SyntaxError". Die Sequenzen sind damit ungültig, wenn nicht die Raw-
String-Schreibweise verwendet oder die Backslashes maskiert werden.

+---------------------+--------------------+
| Gewöhnliche         | Raw-String         |
| Zeichenkette        |                    |
|=====================|====================|
| ""ab*""             | "r"ab*""           |
+---------------------+--------------------+
| ""\\\\section""     | "r"\\section""     |
+---------------------+--------------------+
| ""\\w+\\s+\\1""     | "r"\w+\s+\1""      |
+---------------------+--------------------+


Suchen durchführen
------------------

Du hast nun ein Objekt, das einen übersetzten regulären Ausdruck
darstellt – was machst du damit?  Musterobjekte haben mehrere Methoden
und Attribute. Hier werden nur die wichtigsten behandelt. Eine
vollständige Auflistung findest du in der Dokumentation zu "re".

+--------------------+-------------------------------------------------+
| Methode/Attribut   | Zweck                                           |
|====================|=================================================|
| "search()"         | Eine Zeichenkette durchsuchen und jede Stelle   |
|                    | finden, an der dieser RE passt.                 |
+--------------------+-------------------------------------------------+
| "prefixmatch()"    | Feststellen, ob der RE am Anfang der            |
|                    | Zeichenkette passt. Früher match() genannt.     |
+--------------------+-------------------------------------------------+
| "findall()"        | Alle Teilzeichenketten finden, auf die der RE   |
|                    | passt, und sie als Liste zurückgeben.           |
+--------------------+-------------------------------------------------+
| "finditer()"       | Alle Teilzeichenketten finden, auf die der RE   |
|                    | passt, und sie als *Iterator* zurückgeben.      |
+--------------------+-------------------------------------------------+

"search()" und "prefixmatch()" geben "None" zurück, wenn keine
Fundstelle gefunden wird.  Sind sie erfolgreich, wird eine Instanz
eines Match-Objekts zurückgegeben, die Informationen über die
Fundstelle enthält: wo sie beginnt und endet, auf welche
Teilzeichenkette sie gepasst hat und mehr.

Das lernst du am besten, indem du interaktiv mit dem Modul "re"
herumprobierst.

Dieses HOWTO verwendet für seine Beispiele den gewöhnlichen Python-
Interpreter. Starte zunächst den Python-Interpreter, importiere das
Modul "re" und übersetze einen RE:

   >>> import re
   >>> p = re.compile('[a-z]+')
   >>> p
   re.compile('[a-z]+')

Jetzt kannst du verschiedene Zeichenketten gegen den RE "[a-z]+"
prüfen. Eine leere Zeichenkette sollte überhaupt nicht passen, denn
"+" bedeutet „eine oder mehr Wiederholungen“. "search()" sollte in
diesem Fall "None" zurückgeben, weshalb der Interpreter nichts
ausgibt.  Du kannst das Ergebnis von "search()" ausdrücklich ausgeben,
um das deutlich zu machen.

   >>> p.search("")
   >>> print(p.search(""))
   None

Probieren wir es nun an einer Zeichenkette, auf die er passen sollte,
etwa "tempo".  In diesem Fall gibt "search()" ein Match-Objekt zurück,
du solltest das Ergebnis also für die spätere Verwendung in einer
Variablen ablegen.

   >>> m = p.search('tempo')
   >>> m
   <re.Match object; span=(0, 5), match='tempo'>

Jetzt kannst du das Match-Objekt nach Informationen über die passende
Zeichenkette befragen.  Instanzen von Match-Objekten haben ebenfalls
mehrere Methoden und Attribute. Die wichtigsten sind:

+--------------------+----------------------------------------------+
| Methode/Attribut   | Zweck                                        |
|====================|==============================================|
| "group()"          | Gibt die Zeichenkette zurück, auf die der RE |
|                    | gepasst hat                                  |
+--------------------+----------------------------------------------+
| "start()"          | Gibt die Anfangsposition der Fundstelle      |
|                    | zurück                                       |
+--------------------+----------------------------------------------+
| "end()"            | Gibt die Endposition der Fundstelle zurück   |
+--------------------+----------------------------------------------+
| "span()"           | Gibt ein Tupel mit den Positionen (Anfang,   |
|                    | Ende)  der Fundstelle zurück                 |
+--------------------+----------------------------------------------+

Diese Methoden auszuprobieren macht ihre Bedeutung schnell klar:

   >>> m.group()
   'tempo'
   >>> m.start(), m.end()
   (0, 5)
   >>> m.span()
   (0, 5)

"group()" gibt die Teilzeichenkette zurück, auf die der RE gepasst
hat.  "start()" und "end()" geben den Anfangs- und den Endindex der
Fundstelle zurück. "span()" gibt Anfangs- und Endindex zusammen in
einem einzigen Tupel zurück. Die Methode "search()" von Mustern
durchsucht die Zeichenkette, die Fundstelle muss also nicht bei null
beginnen. Die Methode "prefixmatch()" prüft dagegen nur, ob der RE am
Anfang einer Zeichenkette passt, deshalb ist "start()" in diesem Fall
immer null.

   >>> m = p.search('::: message'); print(m)
   <re.Match object; span=(4, 11), match='message'>
   >>> m.group()
   'message'
   >>> m.span()
   (4, 11)
   >>> print(p.prefixmatch('::: message'))
   None

In echten Programmen ist es am üblichsten, das Match-Objekt in einer
Variablen abzulegen und dann zu prüfen, ob es "None" war.  Das sieht
meist so aus:

   p = re.compile( ... )
   m = p.search( 'string goes here' )
   if m:
       print('Match found: ', m.group())
   else:
       print('No match')

Zwei Methoden von Mustern geben alle Fundstellen eines Musters zurück.
"findall()" gibt eine Liste der passenden Zeichenketten zurück:

   >>> p = re.compile(r'\d+')
   >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
   ['12', '11', '10']

Das Präfix "r", das aus dem Literal ein Raw-String-Literal macht, ist
in diesem Beispiel nötig, weil Escape-Sequenzen in einem gewöhnlichen
(„cooked“) Zeichenkettenliteral, die Python – im Unterschied zu
regulären Ausdrücken – nicht kennt, jetzt zu einer "SyntaxWarning"
führen und später zu einem "SyntaxError" werden.  Siehe Die Backslash-
Plage.

"findall()" muss die gesamte Liste aufbauen, bevor sie als Ergebnis
zurückgegeben werden kann.  Die Methode "finditer()" gibt eine Folge
von Instanzen eines Match-Objekts als *Iterator* zurück:

   >>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
   >>> iterator
   <callable_iterator object at 0x...>
   >>> for match in iterator:
   ...     print(match.span())
   ...
   (0, 2)
   (22, 24)
   (29, 31)


Funktionen auf Modulebene
-------------------------

Du musst kein Musterobjekt erzeugen und dessen Methoden aufrufen. Das
Modul "re" bietet auch Funktionen auf oberster Ebene namens
"search()", "prefixmatch()", "findall()", "sub()" und so weiter.
Diese Funktionen nehmen die gleichen Argumente wie die entsprechende
Methode des Musters, ergänzt um die RE-Zeichenkette als erstes
Argument, und geben weiterhin entweder "None" oder eine Instanz eines
Match-Objekts zurück.

   >>> print(re.prefixmatch(r'From\s+', 'Fromage amk'))
   None
   >>> re.prefixmatch(r'From\s+', 'From amk Thu May 14 19:12:10 1998')
   <re.Match object; span=(0, 5), match='From '>

Unter der Haube erzeugen diese Funktionen einfach ein Musterobjekt für
dich und rufen die passende Methode darauf auf.  Sie legen das
übersetzte Objekt außerdem in einem Zwischenspeicher ab, sodass
spätere Aufrufe mit demselben RE das Muster nicht immer wieder neu
zerlegen müssen.

Solltest du diese Funktionen auf Modulebene verwenden, oder solltest
du dir das Muster holen und seine Methoden selbst aufrufen?  Greifst
du innerhalb einer Schleife auf einen Regex zu, sparst du durch
vorheriges Übersetzen einige Funktionsaufrufe. Außerhalb von Schleifen
macht es dank des internen Zwischenspeichers kaum einen Unterschied.


Flags beim Übersetzen
---------------------

Flags beim Übersetzen erlauben dir, einige Aspekte der Arbeitsweise
regulärer Ausdrücke zu verändern. Die Flags stehen im Modul "re" unter
zwei Namen bereit: einem langen Namen wie "IGNORECASE" und einer
kurzen Form aus einem Buchstaben wie "I".  (Kennst du Perls
Mustermodifikatoren, so verwenden die Einbuchstabenformen die gleichen
Buchstaben. Die Kurzform von "re.VERBOSE" ist zum Beispiel "re.X".)
Mehrere Flags lassen sich durch bitweises ODER angeben; "re.I | re.M"
setzt zum Beispiel sowohl das Flag "I" als auch "M".

Hier eine Tabelle der verfügbaren Flags, gefolgt von einer
ausführlicheren Erklärung jedes einzelnen.

+-----------------------------------+----------------------------------------------+
| Flag                              | Bedeutung                                    |
|===================================|==============================================|
| "ASCII", "A"                      | Lässt mehrere Escapes wie "\w", "\b", "\s"   |
|                                   | und "\d" nur auf ASCII- Zeichen mit der      |
|                                   | jeweiligen Eigenschaft passen.               |
+-----------------------------------+----------------------------------------------+
| "DOTALL", "S"                     | Lässt "." auf jedes Zeichen passen, auch auf |
|                                   | Zeilenumbrüche.                              |
+-----------------------------------+----------------------------------------------+
| "IGNORECASE", "I"                 | Sucht ohne Rücksicht auf Groß- und           |
|                                   | Kleinschreibung.                             |
+-----------------------------------+----------------------------------------------+
| "LOCALE", "L"                     | Sucht unter Berücksichtigung des             |
|                                   | Gebietsschemas.                              |
+-----------------------------------+----------------------------------------------+
| "MULTILINE", "M"                  | Mehrzeilige Suche, wirkt auf "^" und "$".    |
+-----------------------------------+----------------------------------------------+
| "VERBOSE", "X" (für „extended“)   | Schaltet ausführliche REs ein, die sich      |
|                                   | übersichtlicher und verständlicher gliedern  |
|                                   | lassen.                                      |
+-----------------------------------+----------------------------------------------+

re.I
re.IGNORECASE

   Sucht ohne Rücksicht auf Groß- und Kleinschreibung; Zeichenklassen
   und wörtliche Zeichenketten passen auf Buchstaben, ohne die
   Schreibweise zu beachten.  "[A-Z]" passt dann zum Beispiel auch auf
   Kleinbuchstaben. Vollständiges Unicode-Verhalten gilt ebenfalls,
   sofern nicht das Flag "ASCII" Fundstellen außerhalb von ASCII
   abschaltet.  Werden die Unicode-Muster "[a-z]" oder "[A-Z]" mit dem
   Flag "IGNORECASE" verwendet, passen sie auf die 52 ASCII-Buchstaben
   und 4 weitere Buchstaben außerhalb von ASCII: „İ“ (U+0130,
   lateinischer Großbuchstabe I mit Punkt darüber), „ı“ (U+0131,
   lateinischer Kleinbuchstabe i ohne Punkt), „ſ“ (U+017F,
   lateinischer Kleinbuchstabe langes s) und „K“ (U+212A, Kelvin-
   Zeichen).  "Spam" passt auf "'Spam'", "'spam'", "'spAM'" oder
   "'ſpam'" (letzteres nur im Unicode-Modus). Dieses Kleinschreiben
   berücksichtigt das aktuelle Gebietsschema nicht. Das tut es, wenn
   du zusätzlich das Flag "LOCALE" setzt.

re.L
re.LOCALE

   Macht "\w", "\W", "\b", "\B" und die Suche ohne Rücksicht auf Groß-
   und Kleinschreibung vom aktuellen Gebietsschema abhängig statt von
   der Unicode-Datenbank.

   Gebietsschemata sind eine Einrichtung der C-Bibliothek, die beim
   Schreiben von Programmen helfen soll, die sprachliche Unterschiede
   berücksichtigen. Verarbeitest du zum Beispiel kodierten
   französischen Text, möchtest du "\w+" schreiben können, um auf
   Wörter zu passen, aber "\w" passt in Bytes-Mustern nur auf die
   Zeichenklasse "[A-Za-z]". Es passt nicht auf die Bytes, die "é"
   oder "ç" entsprechen. Ist dein System richtig eingerichtet und ein
   französisches Gebietsschema ausgewählt, teilen bestimmte
   C-Funktionen dem Programm mit, dass das Byte für "é" ebenfalls als
   Buchstabe gelten soll. Setzt du beim Übersetzen eines regulären
   Ausdrucks das Flag "LOCALE", verwendet das entstehende übersetzte
   Objekt für "\w" diese C-Funktionen. Das ist langsamer, dafür passt
   "\w+" dann wie erwartet auf französische Wörter. Von diesem Flag
   wird in Python 3 abgeraten, weil der Gebietsschema-Mechanismus sehr
   unzuverlässig ist, immer nur einen „Kulturraum“ gleichzeitig
   behandelt und nur mit 8-Bit-Gebietsschemata funktioniert.  Unicode-
   Verhalten ist in Python 3 für Unicode-Muster (str) ohnehin
   standardmäßig eingeschaltet und kommt mit verschiedenen
   Gebietsschemata und Sprachen zurecht.

re.M
re.MULTILINE

   ("^" und "$" wurden noch nicht erklärt. Sie werden im Abschnitt
   Weitere Metazeichen eingeführt.)

   Normalerweise passt "^" nur am Anfang der Zeichenkette, und "$"
   passt nur am Ende der Zeichenkette sowie unmittelbar vor dem
   Zeilenumbruch (falls vorhanden) am Ende der Zeichenkette. Ist
   dieses Flag angegeben, passt "^" am Anfang der Zeichenkette und am
   Anfang jeder Zeile innerhalb der Zeichenkette, also unmittelbar
   nach jedem Zeilenumbruch.  Entsprechend passt das Metazeichen "$"
   sowohl am Ende der Zeichenkette als auch am Ende jeder Zeile (also
   unmittelbar vor jedem Zeilenumbruch).

re.S
re.DOTALL

   Lässt das besondere Zeichen "'.'" auf wirklich jedes Zeichen
   passen, auch auf einen Zeilenumbruch. Ohne dieses Flag passt "'.'"
   auf alles *außer* einem Zeilenumbruch.

re.A
re.ASCII

   Lässt "\w", "\W", "\b", "\B", "\s" und "\S" nur auf ASCII passen
   statt auf vollständiges Unicode. Das ist nur für Unicode-Muster von
   Bedeutung und wird bei Bytes-Mustern ignoriert.

re.X
re.VERBOSE

   Mit diesem Flag kannst du besser lesbare reguläre Ausdrücke
   schreiben, weil du mehr Freiheit bei ihrer Formatierung hast.  Ist
   dieses Flag angegeben, wird Leerraum innerhalb der RE-Zeichenkette
   ignoriert, außer wenn er in einer Zeichenklasse steht oder ein
   nicht maskierter Backslash davorsteht. Damit kannst du den RE
   übersichtlicher gliedern und einrücken.  Dieses Flag erlaubt dir
   außerdem, Kommentare in einen RE zu schreiben, die die Maschine
   ignoriert; Kommentare werden mit einem "'#'" eingeleitet, das weder
   in einer Zeichenklasse steht noch einen nicht maskierten Backslash
   davor hat.

   Hier zum Beispiel ein RE, der "re.VERBOSE" verwendet. Siehst du,
   wie viel leichter er zu lesen ist?

      charref = re.compile(r"""
       &[#]                # Start of a numeric entity reference
       (
           0[0-7]+         # Octal form
         | [0-9]+          # Decimal form
         | x[0-9a-fA-F]+   # Hexadecimal form
       )
       ;                   # Trailing semicolon
      """, re.VERBOSE)

   Ohne die ausführliche Einstellung sähe der RE so aus:

      charref = re.compile("&#(0[0-7]+"
                           "|[0-9]+"
                           "|x[0-9a-fA-F]+);")

   Im obigen Beispiel wurde Pythons automatisches Verketten von
   Zeichenkettenliteralen genutzt, um den RE in kleinere Stücke zu
   zerlegen, aber er ist immer noch schwerer zu verstehen als die
   Fassung mit "re.VERBOSE".


Mehr Kraft im Muster
====================

Bisher haben wir nur einen Teil der Fähigkeiten regulärer Ausdrücke
behandelt.  In diesem Abschnitt behandeln wir einige neue Metazeichen
und wie du mit Gruppen Teile des gefundenen Textes auslesen kannst.


Weitere Metazeichen
-------------------

Es gibt einige Metazeichen, die wir noch nicht behandelt haben.  Die
meisten davon kommen in diesem Abschnitt zur Sprache.

Einige der noch zu besprechenden Metazeichen sind *Zusicherungen der
Breite null*.  Sie bringen die Maschine nicht dazu, in der
Zeichenkette voranzugehen. Sie verbrauchen überhaupt keine Zeichen und
gelingen oder scheitern einfach.  "\b" ist zum Beispiel eine
Zusicherung, dass die aktuelle Position an einer Wortgrenze liegt. Die
Position wird durch das "\b" überhaupt nicht verändert.  Das bedeutet,
dass Zusicherungen der Breite null niemals wiederholt werden sollten,
denn wenn sie an einer Stelle einmal passen, können sie dort
offensichtlich unendlich oft passen.

"|"
   Alternative, also der „oder“-Operator.   Sind *A* und *B* reguläre
   Ausdrücke, passt "A|B" auf jede Zeichenkette, auf die entweder *A*
   oder *B* passt. "|" hat eine sehr niedrige Bindungsstärke, damit es
   vernünftig arbeitet, wenn du Zeichenketten aus mehreren Zeichen
   gegeneinanderstellst. "Crow|Servo" passt entweder auf "'Crow'" oder
   auf "'Servo'", nicht auf "'Cro'", ein "'w'" oder ein "'S'" und
   "'ervo'".

   Um auf ein wörtliches "'|'" zu passen, verwende "\|" oder schließe
   es in eine Zeichenklasse ein, etwa als "[|]".

"^"
   Passt am Anfang von Zeilen.  Sofern nicht das Flag "MULTILINE"
   gesetzt ist, passt es nur am Anfang der Zeichenkette.  Im Modus
   "MULTILINE" passt es außerdem unmittelbar nach jedem Zeilenumbruch
   innerhalb der Zeichenkette.

   Willst du zum Beispiel auf das Wort "From" nur am Zeilenanfang
   passen, lautet der zu verwendende RE "^From".

      >>> print(re.search('^From', 'From Here to Eternity'))
      <re.Match object; span=(0, 4), match='From'>
      >>> print(re.search('^From', 'Reciting From Memory'))
      None

   Um auf ein wörtliches "'^'" zu passen, verwende "\^".

"$"
   Passt am Ende einer Zeile, das entweder als Ende der Zeichenkette
   oder als jede Stelle definiert ist, auf die ein
   Zeilenumbruchzeichen folgt.

      >>> print(re.search('}$', '{block}'))
      <re.Match object; span=(6, 7), match='}'>
      >>> print(re.search('}$', '{block} '))
      None
      >>> print(re.search('}$', '{block}\n'))
      <re.Match object; span=(6, 7), match='}'>

   Um auf ein wörtliches "'$'" zu passen, verwende "\$" oder schließe
   es in eine Zeichenklasse ein, etwa als  "[$]".

"\A"
   Passt nur am Anfang der Zeichenkette.  Außerhalb des Modus
   "MULTILINE" sind "\A" und "^" praktisch dasselbe.  Im Modus
   "MULTILINE" unterscheiden sie sich: "\A" passt weiterhin nur am
   Anfang der Zeichenkette, "^" kann aber an jeder Stelle innerhalb
   der Zeichenkette passen, die auf ein Zeilenumbruchzeichen folgt.

"\z"
   Passt nur am Ende der Zeichenkette.

"\Z"
   Dasselbe wie "\z".  Zur Verträglichkeit mit alten Python-Versionen.

"\b"
   Wortgrenze.  Das ist eine Zusicherung der Breite null, die nur am
   Anfang oder Ende eines Wortes passt.  Ein Wort ist als Folge
   alphanumerischer Zeichen definiert, das Ende eines Wortes wird also
   durch Leerraum oder ein nicht alphanumerisches Zeichen angezeigt.

   Das folgende Beispiel passt auf "class" nur dann, wenn es ein
   vollständiges Wort ist. Es passt nicht, wenn es in einem anderen
   Wort steckt.

      >>> p = re.compile(r'\bclass\b')
      >>> print(p.search('no class at all'))
      <re.Match object; span=(3, 8), match='class'>
      >>> print(p.search('the declassified algorithm'))
      None
      >>> print(p.search('one subclass is'))
      None

   Bei dieser besonderen Sequenz solltest du an zwei Feinheiten
   denken. Erstens ist das die schlimmste Kollision zwischen Pythons
   Zeichenkettenliteralen und den Sequenzen regulärer Ausdrücke.  In
   Pythons Zeichenkettenliteralen ist "\b" das Rückschrittzeichen mit
   dem ASCII-Wert 8.  Verwendest du keine Raw-Strings, wandelt Python
   das "\b" in einen Rückschritt um, und dein RE passt nicht wie
   erwartet. Das folgende Beispiel sieht genauso aus wie unser
   vorheriger RE, lässt aber das "'r'" vor der RE-Zeichenkette weg.

      >>> p = re.compile('\bclass\b')
      >>> print(p.search('no class at all'))
      None
      >>> print(p.search('\b' + 'class' + '\b'))
      <re.Match object; span=(0, 7), match='\x08class\x08'>

   Zweitens steht "\b" innerhalb einer Zeichenklasse, wo diese
   Zusicherung keinen Sinn hätte, für das Rückschrittzeichen – zur
   Verträglichkeit mit Pythons Zeichenkettenliteralen.

"\B"
   Eine weitere Zusicherung der Breite null. Sie ist das Gegenteil von
   "\b" und passt nur, wenn die aktuelle Position *nicht* an einer
   Wortgrenze liegt.


Gruppierung
-----------

Häufig brauchst du mehr Informationen als nur die, ob der RE gepasst
hat oder nicht.  Reguläre Ausdrücke werden oft verwendet, um
Zeichenketten zu zerlegen. Dazu schreibt man einen RE, der in mehrere
Untergruppen aufgeteilt ist, die auf die verschiedenen
interessierenden Bestandteile passen. Eine Kopfzeile nach RFC 822 ist
zum Beispiel in einen Kopfzeilennamen und einen Wert aufgeteilt,
getrennt durch ein "':'", etwa so:

   From: author@example.com
   User-Agent: Thunderbird 1.5.0.9 (X11/20061227)
   MIME-Version: 1.0
   To: editor@example.com

Das lässt sich handhaben, indem man einen regulären Ausdruck schreibt,
der auf eine ganze Kopfzeile passt und eine Gruppe für den
Kopfzeilennamen sowie eine weitere Gruppe für den Wert der Kopfzeile
hat.

Gruppen werden mit den Metazeichen "'('" und "')'" markiert. "'('" und
"')'" haben weitgehend dieselbe Bedeutung wie in mathematischen
Ausdrücken. Sie fassen die darin enthaltenen Ausdrücke zusammen, und
du kannst den Inhalt einer Gruppe mit einem Quantor wie "*", "+", "?"
oder "{m,n}" wiederholen.  "(ab)*" passt zum Beispiel auf null oder
mehr Wiederholungen von "ab".

   >>> p = re.compile('(ab)*')
   >>> print(p.search('ababababab').span())
   (0, 10)

Gruppen, die mit "'('" und "')'" angezeigt werden, erfassen außerdem
den Anfangs- und Endindex des Textes, auf den sie passen. Die lassen
sich auslesen, indem du "group()", "start()", "end()" und "span()" ein
Argument übergibst. Gruppen werden ab 0 gezählt.  Gruppe 0 ist immer
vorhanden. Sie ist der gesamte RE, deshalb haben alle Methoden des
Match-Objekts Gruppe 0 als Standardargument.  Später sehen wir, wie
man Gruppen formuliert, die den Textbereich, auf den sie passen, nicht
erfassen.

   >>> p = re.compile('(a)b')
   >>> m = p.search('ab')
   >>> m.group()
   'ab'
   >>> m.group(0)
   'ab'

Untergruppen werden von links nach rechts ab 1 aufwärts gezählt.
Gruppen können verschachtelt sein. Um die Nummer zu bestimmen, zähle
einfach die öffnenden Klammern von links nach rechts.

   >>> p = re.compile('(a(b)c)d')
   >>> m = p.search('abcd')
   >>> m.group(0)
   'abcd'
   >>> m.group(1)
   'abc'
   >>> m.group(2)
   'b'

"group()" lassen sich mehrere Gruppennummern auf einmal übergeben. In
diesem Fall gibt sie ein Tupel mit den entsprechenden Werten dieser
Gruppen zurück.

   >>> m.group(2,1,2)
   ('b', 'abc', 'b')

Die Methode "groups()" gibt ein Tupel mit den Zeichenketten aller
Untergruppen zurück, von 1 bis zu so vielen, wie es gibt.

   >>> m.groups()
   ('abc', 'b')

Rückwärtsverweise in einem Muster erlauben dir anzugeben, dass der
Inhalt einer früheren erfassenden Gruppe auch an der aktuellen Stelle
in der Zeichenkette zu finden sein muss.  "\1" gelingt zum Beispiel,
wenn genau der Inhalt von Gruppe 1 an der aktuellen Position gefunden
wird, und scheitert andernfalls.  Denk daran, dass Pythons
Zeichenkettenliterale ebenfalls einen Backslash gefolgt von Zahlen
verwenden, um beliebige Zeichen in eine Zeichenkette aufzunehmen.
Verwende also unbedingt einen Raw-String, wenn du Rückwärtsverweise in
einen RE einbaust.

Der folgende RE findet zum Beispiel doppelte Wörter in einer
Zeichenkette.

   >>> p = re.compile(r'\b(\w+)\s+\1\b')
   >>> p.search('Paris in the the spring').group()
   'the the'

Solche Rückwärtsverweise sind zum reinen Durchsuchen einer
Zeichenkette selten nützlich --- es gibt wenige Textformate, die Daten
auf diese Weise wiederholen ---, aber du wirst schnell merken, dass
sie beim Ersetzen in Zeichenketten *sehr* nützlich sind.


Nicht erfassende und benannte Gruppen
-------------------------------------

Ausgefeilte REs verwenden möglicherweise viele Gruppen, sowohl um
interessierende Teilzeichenketten zu erfassen als auch um den RE
selbst zu gliedern und zu strukturieren.  In komplexen REs wird es
schwierig, die Gruppennummern im Blick zu behalten.  Es gibt zwei
Einrichtungen, die bei diesem Problem helfen.  Beide nutzen eine
gemeinsame Syntax für Erweiterungen regulärer Ausdrücke, die wir uns
daher zuerst ansehen.

Perl 5 ist für seine mächtigen Ergänzungen zu den gewöhnlichen
regulären Ausdrücken bekannt. Für diese neuen Fähigkeiten konnten die
Perl-Entwickler keine neuen Metazeichen aus einem Tastendruck und
keine neuen besonderen Sequenzen mit "\" wählen, ohne Perls reguläre
Ausdrücke verwirrend anders als die gewöhnlichen REs zu machen.
Hätten sie zum Beispiel "&" als neues Metazeichen gewählt, hätten alte
Ausdrücke angenommen, dass "&" ein gewöhnliches Zeichen ist, und es
nicht als "\&" oder "[&]" maskiert.

Die von den Perl-Entwicklern gewählte Lösung war, "(?...)" als
Erweiterungssyntax zu verwenden.  Ein "?" unmittelbar nach einer
Klammer war ein Syntaxfehler, weil das "?" nichts zu wiederholen
gehabt hätte. So entstanden keine Verträglichkeitsprobleme.  Die
Zeichen unmittelbar nach dem "?"  zeigen an, welche Erweiterung
verwendet wird, "(?=foo)" ist also eine Sache (eine positive
Lookahead-Zusicherung) und "(?:foo)" etwas anderes (eine nicht
erfassende Gruppe mit dem Teilausdruck "foo").

Python unterstützt mehrere von Perls Erweiterungen und ergänzt Perls
Erweiterungssyntax um eine eigene Erweiterungssyntax.  Ist das erste
Zeichen nach dem Fragezeichen ein "P", weißt du, dass es sich um eine
Erweiterung handelt, die es nur in Python gibt.

Nachdem wir uns die allgemeine Erweiterungssyntax angesehen haben,
können wir zu den Einrichtungen zurückkehren, die die Arbeit mit
Gruppen in komplexen REs vereinfachen.

Manchmal willst du mit einer Gruppe einen Teil eines regulären
Ausdrucks abgrenzen, bist aber nicht daran interessiert, den Inhalt
der Gruppe auszulesen. Das kannst du ausdrücklich machen, indem du
eine nicht erfassende Gruppe verwendest: "(?:...)", wobei du die "..."
durch jeden anderen regulären Ausdruck ersetzen kannst.

   >>> m = re.search("([abc])+", "abc")
   >>> m.groups()
   ('c',)
   >>> m = re.search("(?:[abc])+", "abc")
   >>> m.groups()
   ()

Abgesehen davon, dass du den Inhalt nicht auslesen kannst, auf den die
Gruppe gepasst hat, verhält sich eine nicht erfassende Gruppe genau
wie eine erfassende. Du kannst alles hineinschreiben, sie mit einem
Wiederholungsmetazeichen wie "*" wiederholen und sie in andere Gruppen
(erfassende oder nicht erfassende) verschachteln.  "(?:...)" ist
besonders nützlich, wenn du ein bestehendes Muster änderst, denn du
kannst neue Gruppen ergänzen, ohne die Nummerierung aller anderen
Gruppen zu verändern. Es sei erwähnt, dass es beim Suchen keinen
Geschwindigkeitsunterschied zwischen erfassenden und nicht erfassenden
Gruppen gibt. Keine der beiden Formen ist schneller als die andere.

Eine wichtigere Einrichtung sind benannte Gruppen: Statt sie über
Nummern anzusprechen, lassen sich Gruppen über einen Namen ansprechen.

Die Syntax für eine benannte Gruppe ist eine der Erweiterungen, die es
nur in Python gibt: "(?P<name>...)".  *name* ist, wie zu erwarten, der
Name der Gruppe.  Benannte Gruppen verhalten sich genau wie erfassende
Gruppen und verbinden zusätzlich einen Namen mit einer Gruppe.  Die
Methoden des Match-Objekts, die mit erfassenden Gruppen umgehen,
nehmen alle entweder Ganzzahlen, die die Gruppe über ihre Nummer
ansprechen, oder Zeichenketten mit dem Namen der gewünschten Gruppe.
Benannte Gruppen erhalten weiterhin Nummern, du kannst Informationen
über eine Gruppe also auf zwei Wegen auslesen:

   >>> p = re.compile(r'(?P<word>\b\w+\b)')
   >>> m = p.search( '(((( Lots of punctuation )))' )
   >>> m.group('word')
   'Lots'
   >>> m.group(1)
   'Lots'

Darüber hinaus kannst du benannte Gruppen mit "groupdict()" als
Dictionary auslesen:

   >>> m = re.search(r'(?P<first>\w+) (?P<last>\w+)', 'Jane Doe')
   >>> m.groupdict()
   {'first': 'Jane', 'last': 'Doe'}

Benannte Gruppen sind praktisch, weil du damit leicht einprägsame
Namen verwenden kannst, statt dir Nummern merken zu müssen.  Hier ein
Beispiel-RE aus dem Modul "imaplib":

   InternalDate = re.compile(r'INTERNALDATE "'
           r'(?P<day>[ 123][0-9])-(?P<mon>[A-Z][a-z][a-z])-'
           r'(?P<year>[0-9][0-9][0-9][0-9])'
           r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])'
           r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])'
           r'"')

Es ist offensichtlich viel einfacher, "m.group('zonem')" auszulesen,
als sich zu merken, dass man Gruppe 9 auslesen muss.

Die Syntax für Rückwärtsverweise in einem Ausdruck wie "(...)\1"
spricht die Nummer der Gruppe an.  Es gibt natürlich eine Variante,
die den Gruppennamen statt der Nummer verwendet. Das ist eine weitere
Python-Erweiterung: "(?P=name)" zeigt an, dass der Inhalt der Gruppe
namens *name* an der aktuellen Stelle erneut passen soll.  Der
reguläre Ausdruck zum Finden doppelter Wörter, "\b(\w+)\s+\1\b", lässt
sich auch als "\b(?P<word>\w+)\s+(?P=word)\b" schreiben:

   >>> p = re.compile(r'\b(?P<word>\w+)\s+(?P=word)\b')
   >>> p.search('Paris in the the spring').group()
   'the the'


Lookahead-Zusicherungen
-----------------------

Eine weitere Zusicherung der Breite null ist die Lookahead-
Zusicherung. Lookahead-Zusicherungen gibt es in positiver und
negativer Form, und sie sehen so aus:

"(?=...)"
   Positive Lookahead-Zusicherung.  Sie gelingt, wenn der enthaltene
   reguläre Ausdruck, hier durch "..." dargestellt, an der aktuellen
   Stelle erfolgreich passt, und scheitert andernfalls. Nachdem der
   enthaltene Ausdruck aber versucht wurde, geht die Suchmaschine
   überhaupt nicht voran. Der Rest des Musters wird genau dort
   versucht, wo die Zusicherung begonnen hat.

"(?!...)"
   Negative Lookahead-Zusicherung.  Sie ist das Gegenteil der
   positiven Zusicherung. Sie gelingt, wenn der enthaltene Ausdruck an
   der aktuellen Position in der Zeichenkette *nicht* passt.

Um das greifbar zu machen, sehen wir uns einen Fall an, in dem ein
Lookahead nützlich ist. Stell dir ein einfaches Muster vor, das auf
einen Dateinamen passt und ihn in einen Basisnamen und eine Endung
zerlegt, getrennt durch einen ".".  In "news.rc" ist zum Beispiel
"news" der Basisname und "rc" die Endung des Dateinamens.

Das Muster dafür ist recht einfach:

".*[.].*$"

Beachte, dass der "." besonders behandelt werden muss, weil er ein
Metazeichen ist. Er steht deshalb in einer Zeichenklasse, damit er nur
auf genau dieses Zeichen passt.  Beachte außerdem das abschließende
"$". Es sorgt dafür, dass der gesamte Rest der Zeichenkette zur Endung
gehören muss. Dieser reguläre Ausdruck passt auf "foo.bar",
"autoexec.bat", "sendmail.cf" und "printers.conf".

Machen wir das Problem nun etwas komplizierter: Was, wenn du auf
Dateinamen passen willst, deren Endung *nicht* "bat" ist? Einige
fehlerhafte Versuche:

".*[.][^b].*$"

Der erste Versuch oben will "bat" ausschließen, indem er verlangt,
dass das erste Zeichen der Endung kein "b" ist.  Das ist falsch, weil
das Muster dann auch nicht auf "foo.bar" passt.

".*[.]([^b]..|.[^a].|..[^t])$"

Der Ausdruck wird unübersichtlicher, wenn du die erste Lösung
ausbessern willst, indem du verlangst, dass einer der folgenden Fälle
passt: Das erste Zeichen der Endung ist kein "b", das zweite Zeichen
ist kein "a", oder das dritte Zeichen ist kein "t".  Das nimmt
"foo.bar" an und weist "autoexec.bat" zurück, verlangt aber eine
dreibuchstabige Endung und nimmt keinen Dateinamen mit
zweibuchstabiger Endung wie "sendmail.cf" an.  Wir machen das Muster
also erneut komplizierter, um das zu beheben.

".*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$"

Im dritten Versuch werden der zweite und dritte Buchstabe optional
gemacht, damit auch Endungen mit weniger als drei Zeichen passen, etwa
"sendmail.cf".

Das Muster wird jetzt richtig kompliziert, was es schwer lesbar und
schwer verständlich macht.  Schlimmer noch: Ändert sich die Aufgabe
und du willst sowohl "bat" als auch "exe" als Endung ausschließen,
würde das Muster noch komplizierter und verwirrender.

Ein negativer Lookahead schneidet diese ganze Verwirrung ab:

".*[.](?!bat$)[^.]*$"

Der negative Lookahead bedeutet: Passt der Ausdruck "bat" an dieser
Stelle nicht, versuche den Rest des Musters. Passt "bat$" doch,
scheitert das gesamte Muster.  Das abschließende "$" ist nötig, damit
etwas wie "sample.batch", dessen Endung nur mit "bat" beginnt,
zugelassen wird. Das "[^.]*" stellt sicher, dass das Muster auch dann
funktioniert, wenn der Dateiname mehrere Punkte enthält.

Eine weitere Dateiendung auszuschließen ist nun leicht. Ergänze sie
einfach als Alternative innerhalb der Zusicherung.  Das folgende
Muster schließt Dateinamen aus, die entweder auf "bat" oder auf "exe"
enden:

".*[.](?!bat$|exe$)[^.]*$"


Zeichenketten verändern
=======================

Bis hierher haben wir nur in einer unveränderlichen Zeichenkette
gesucht. Reguläre Ausdrücke werden auch häufig verwendet, um
Zeichenketten auf verschiedene Weisen zu verändern. Dazu dienen die
folgenden Methoden von Mustern:

+--------------------+-------------------------------------------------+
| Methode/Attribut   | Zweck                                           |
|====================|=================================================|
| "split()"          | Zerlegt die Zeichenkette in eine Liste und      |
|                    | trennt sie überall, wo der RE passt             |
+--------------------+-------------------------------------------------+
| "sub()"            | Findet alle Teilzeichenketten, auf die der RE   |
|                    | passt, und ersetzt sie durch eine andere        |
|                    | Zeichenkette                                    |
+--------------------+-------------------------------------------------+
| "subn()"           | Tut dasselbe wie "sub()",  gibt aber die neue   |
|                    | Zeichenkette und die Anzahl der Ersetzungen     |
|                    | zurück                                          |
+--------------------+-------------------------------------------------+


Zeichenketten zerlegen
----------------------

Die Methode "split()" eines Musters zerlegt eine Zeichenkette überall,
wo der RE passt, und gibt eine Liste der Stücke zurück. Sie ähnelt der
Methode "split()" von Zeichenketten, ist bei den Trennzeichen, nach
denen du zerlegen kannst, aber viel allgemeiner; "split()" von
Zeichenketten kann nur nach Leerraum oder nach einer festen
Zeichenkette zerlegen.  Wie zu erwarten gibt es auch eine Funktion
"re.split()" auf Modulebene.

.split(string[, maxsplit=0])

   Zerlegt *string* an den Fundstellen des regulären Ausdrucks.
   Werden im RE erfassende Klammern verwendet, wird auch ihr Inhalt
   als Teil der entstehenden Liste zurückgegeben.  Ist *maxsplit*
   ungleich null, werden höchstens *maxsplit* Trennungen vorgenommen.

Du kannst die Anzahl der Trennungen begrenzen, indem du einen Wert für
*maxsplit* übergibst. Ist *maxsplit* ungleich null, werden höchstens
*maxsplit* Trennungen vorgenommen, und der Rest der Zeichenkette wird
als letztes Element der Liste zurückgegeben.  Im folgenden Beispiel
ist das Trennzeichen jede Folge nicht alphanumerischer Zeichen.

   >>> p = re.compile(r'\W+')
   >>> p.split('This is a test, short and sweet, of split().')
   ['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', '']
   >>> p.split('This is a test, short and sweet, of split().', 3)
   ['This', 'is', 'a', 'test, short and sweet, of split().']

Manchmal interessiert dich nicht nur, was der Text zwischen den
Trennzeichen ist, sondern du musst auch wissen, welches das
Trennzeichen war.  Werden im RE erfassende Klammern verwendet, werden
auch ihre Werte als Teil der Liste zurückgegeben.  Vergleiche die
folgenden Aufrufe:

   >>> p = re.compile(r'\W+')
   >>> p2 = re.compile(r'(\W+)')
   >>> p.split('This... is a test.')
   ['This', 'is', 'a', 'test', '']
   >>> p2.split('This... is a test.')
   ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']

Die Funktion "re.split()" auf Modulebene ergänzt den zu verwendenden
RE als erstes Argument, ist ansonsten aber gleich.

   >>> re.split(r'[\W]+', 'Words, words, words.')
   ['Words', 'words', 'words', '']
   >>> re.split(r'([\W]+)', 'Words, words, words.')
   ['Words', ', ', 'words', ', ', 'words', '.', '']
   >>> re.split(r'[\W]+', 'Words, words, words.', 1)
   ['Words', 'words, words.']


Suchen und ersetzen
-------------------

Eine weitere häufige Aufgabe ist, alle Fundstellen eines Musters zu
finden und sie durch eine andere Zeichenkette zu ersetzen.  Die
Methode "sub()" nimmt einen Ersatzwert, der entweder eine Zeichenkette
oder eine Funktion sein kann, sowie die zu verarbeitende Zeichenkette.

.sub(replacement, string[, count=0])

   Gibt die Zeichenkette zurück, die entsteht, wenn die von links her
   ersten, sich nicht überlappenden Vorkommen des RE in *string* durch
   den Ersatz *replacement* ersetzt werden.  Wird das Muster nicht
   gefunden, wird *string* unverändert zurückgegeben.

   Das optionale Argument *count* ist die größte Anzahl zu ersetzender
   Vorkommen des Musters; *count* muss eine nicht negative Ganzzahl
   sein.  Der Standardwert 0 bedeutet, dass alle Vorkommen ersetzt
   werden.

Hier ein einfaches Beispiel für die Methode "sub()".  Sie ersetzt
Farbnamen durch das Wort "colour":

   >>> p = re.compile('(blue|white|red)')
   >>> p.sub('colour', 'blue socks and red shoes')
   'colour socks and colour shoes'
   >>> p.sub('colour', 'blue socks and red shoes', count=1)
   'colour socks and red shoes'

Die Methode "subn()" leistet dieselbe Arbeit, gibt aber ein 2-Tupel
mit der neuen Zeichenkette und der Anzahl der vorgenommenen
Ersetzungen  zurück:

   >>> p = re.compile('(blue|white|red)')
   >>> p.subn('colour', 'blue socks and red shoes')
   ('colour socks and colour shoes', 2)
   >>> p.subn('colour', 'no colours at all')
   ('no colours at all', 0)

Leere Fundstellen werden nur dann ersetzt, wenn sie nicht unmittelbar
an eine vorherige leere Fundstelle angrenzen.

   >>> p = re.compile('x*')
   >>> p.sub('-', 'abxd')
   '-a-b--d-'

Ist *replacement* eine Zeichenkette, werden alle Backslash-
Maskierungen darin verarbeitet.  Das heißt, "\n" wird in ein einzelnes
Zeilenumbruchzeichen umgewandelt, "\r" in einen Wagenrücklauf und so
weiter. Unbekannte Maskierungen wie "\&" bleiben unangetastet.
Rückwärtsverweise wie "\6" werden durch die Teilzeichenkette ersetzt,
auf die die entsprechende Gruppe im RE gepasst hat.  Damit kannst du
Teile des ursprünglichen Textes in die entstehende Ersatzzeichenkette
einbauen.

Dieses Beispiel passt auf das Wort "section", gefolgt von einer in "{"
und "}" eingeschlossenen Zeichenkette, und ändert "section" in
"subsection":

   >>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
   >>> p.sub(r'subsection{\1}','section{First} section{second}')
   'subsection{First} subsection{second}'

Es gibt außerdem eine Syntax, um benannte Gruppen anzusprechen, wie
sie die Syntax "(?P<name>...)" festlegt.  "\g<name>" verwendet die
Teilzeichenkette, auf die die Gruppe namens "name" gepasst hat, und
"\g<number>"  verwendet die entsprechende Gruppennummer. "\g<2>"
entspricht daher "\2",  ist in einer Ersatzzeichenkette wie "\g<2>0"
aber nicht mehrdeutig.  ("\20" würde als Verweis auf Gruppe 20
verstanden, nicht als Verweis auf Gruppe 2 gefolgt vom wörtlichen
Zeichen "'0'".)  Die folgenden Ersetzungen sind alle gleichwertig,
verwenden aber alle drei Varianten der Ersatzzeichenkette.

   >>> p = re.compile('section{ (?P<name> [^}]* ) }', re.VERBOSE)
   >>> p.sub(r'subsection{\1}','section{First}')
   'subsection{First}'
   >>> p.sub(r'subsection{\g<1>}','section{First}')
   'subsection{First}'
   >>> p.sub(r'subsection{\g<name>}','section{First}')
   'subsection{First}'

*replacement* kann auch eine Funktion sein, was dir noch mehr
Kontrolle gibt.  Ist *replacement* eine Funktion, wird sie für jedes
sich nicht überlappende Vorkommen von *pattern* aufgerufen.  Bei jedem
Aufruf wird der Funktion ein Match-Objekt für die Fundstelle
übergeben. Sie kann daraus die gewünschte Ersatzzeichenkette berechnen
und zurückgeben.

Im folgenden Beispiel übersetzt die Ersatzfunktion Dezimalzahlen in
Hexadezimalzahlen:

   >>> def hexrepl(match):
   ...     "Return the hex string for a decimal number"
   ...     value = int(match.group())
   ...     return hex(value)
   ...
   >>> p = re.compile(r'\d+')
   >>> p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
   'Call 0xffd2 for printing, 0xc000 for user code.'

Verwendest du die Funktion "re.sub()" auf Modulebene, wird das Muster
als erstes Argument übergeben.  Das Muster darf als Objekt oder als
Zeichenkette angegeben werden. Musst du Flags für reguläre Ausdrücke
angeben, musst du entweder ein Musterobjekt als ersten Parameter
verwenden oder eingebettete Modifikatoren in der Musterzeichenkette,
etwa gibt "sub("(?i)b+", "x", "bbbb BBBB")" den Wert "'x x'" zurück.


Häufige Probleme
================

Reguläre Ausdrücke sind für manche Anwendungen ein mächtiges Werkzeug,
aber ihr Verhalten ist in einigen Punkten nicht anschaulich, und
manchmal verhalten sie sich nicht so, wie du es erwarten würdest.
Dieser Abschnitt zeigt einige der häufigsten Fallgruben auf.


Methoden von Zeichenketten verwenden
------------------------------------

Manchmal ist es ein Fehler, das Modul "re" zu verwenden.  Passt du auf
eine feste Zeichenkette oder eine einzelne Zeichenklasse und nutzt
keine Eigenschaften von "re" wie das Flag "IGNORECASE", dann brauchst
du vielleicht nicht die ganze Kraft regulärer Ausdrücke. Zeichenketten
haben mehrere Methoden für Operationen mit festen Zeichenketten, und
die sind meist viel schneller, weil die Umsetzung eine einzige kleine,
dafür optimierte C-Schleife ist statt der großen, allgemeiner
gehaltenen Maschine für reguläre Ausdrücke.

Ein Beispiel wäre, eine einzelne feste Zeichenkette durch eine andere
zu ersetzen. Etwa "word" durch "deed".  "re.sub()" erscheint als die
passende Funktion dafür, aber sieh dir die Methode "replace()" an.
Beachte, dass "replace()" auch "word" innerhalb von Wörtern ersetzt
und aus "swordfish" ein "sdeedfish" macht – aber der  naive RE "word"
hätte das genauso getan.  (Um die Ersetzung nicht in Wortteilen
vorzunehmen, müsste das Muster "\bword\b" lauten, damit "word" auf
beiden Seiten eine Wortgrenze haben muss.  Das geht über die
Fähigkeiten von "replace()" hinaus.)

Eine weitere häufige Aufgabe ist, jedes Vorkommen eines einzelnen
Zeichens aus einer Zeichenkette zu entfernen oder durch ein anderes
einzelnes Zeichen zu ersetzen.  Das könntest du mit etwas wie
"re.sub('\n', ' ', S)" machen, aber "translate()" kann beide Aufgaben
erledigen und ist schneller, als eine Operation mit regulären
Ausdrücken es sein kann.

Kurz gesagt: Überlege vor dem Griff zum Modul "re", ob sich dein
Problem mit einer schnelleren und einfacheren Methode von
Zeichenketten lösen lässt.


prefixmatch() (auch match) gegenüber search()
---------------------------------------------

"prefixmatch()" kam in Python 3.15 als bevorzugter Name für "match()"
hinzu. Davor hieß es nur "match()", und der Unterschied zu "search()"
wurde oft missverstanden.

"prefixmatch()", also "match()", prüft nur, ob der RE am Anfang der
Zeichenkette passt, während "search()" die Zeichenkette vorwärts nach
einer Fundstelle durchsucht.

   >>> print(re.prefixmatch('super', 'superstition').span())
   (0, 5)
   >>> print(re.prefixmatch('super', 'insuperable'))
   None

"search()" durchsucht die Zeichenkette dagegen vorwärts und meldet die
erste Fundstelle, die es findet.

   >>> print(re.search('super', 'superstition').span())
   (0, 5)
   >>> print(re.search('super', 'insuperable').span())
   (2, 7)

An diesen Unterschied solltest du denken, wenn du den alten Namen
"match()" in Code verwendest, der mit älteren Python-Versionen
verträglich sein muss.


Gierig gegenüber nicht gierig
-----------------------------

Beim Wiederholen eines regulären Ausdrucks, etwa in "a*", wird so viel
vom Muster verbraucht wie möglich.  Diese Eigenschaft beißt dich oft,
wenn du auf ein Paar ausgeglichener Trennzeichen passen willst, etwa
auf die spitzen Klammern um ein HTML-Tag.  Das naive Muster zum Passen
auf ein einzelnes HTML-Tag funktioniert wegen der gierigen Natur von
".*" nicht.

   >>> s = '<html><head><title>Title</title>'
   >>> len(s)
   32
   >>> print(re.prefixmatch('<.*>', s).span())
   (0, 32)
   >>> print(re.prefixmatch('<.*>', s).group())
   <html><head><title>Title</title>

Der RE passt auf das "'<'" in "'<html>'", und das ".*" verbraucht den
Rest der Zeichenkette.  Im RE steht aber noch mehr, und das ">" kann
am Ende der Zeichenkette nicht passen, also muss die Maschine für
reguläre Ausdrücke Zeichen für Zeichen zurückgehen, bis sie eine
Fundstelle für das ">" findet.   Die endgültige Fundstelle reicht vom
"'<'" in "'<html>'" bis zum "'>'" in "'</title>'", und das ist nicht,
was du willst.

Die Lösung besteht in diesem Fall darin, die nicht gierigen Quantoren
"*?", "+?", "??" oder "{m,n}?" zu verwenden, die auf so *wenig* Text
wie möglich passen.  Im obigen Beispiel wird das "'>'" unmittelbar
nach der ersten Fundstelle des "'<'" versucht, und wenn es
fehlschlägt, geht die Maschine Zeichen für Zeichen voran und versucht
das "'>'" bei jedem Schritt neu.  Das liefert genau das richtige
Ergebnis:

   >>> print(re.prefixmatch('<.*?>', s).group())
   <html>

(Beachte, dass das Zerlegen von HTML oder XML mit regulären Ausdrücken
mühsam ist. Schnell hingeworfene Muster bewältigen die häufigen Fälle,
aber HTML und XML haben Sonderfälle, an denen der naheliegende
reguläre Ausdruck zerbricht, bis du einen regulären Ausdruck
geschrieben hast, der alle möglichen Fälle behandelt, sind die Muster
*sehr* kompliziert.  Verwende für solche Aufgaben ein Modul zum
Zerlegen von HTML oder XML.)


re.VERBOSE verwenden
--------------------

Inzwischen ist dir wahrscheinlich aufgefallen, dass reguläre Ausdrücke
eine sehr knappe Schreibweise sind, aber nicht besonders lesbar.  REs
mittlerer Komplexität können zu langen Ansammlungen von Backslashes,
Klammern und Metazeichen werden und sind dann schwer zu lesen und zu
verstehen.

Bei solchen REs kann es helfen, beim Übersetzen des regulären
Ausdrucks das Flag "re.VERBOSE" anzugeben, denn damit kannst du den
regulären Ausdruck übersichtlicher formatieren.

Das Flag "re.VERBOSE" hat mehrere Wirkungen.  Leerraum im regulären
Ausdruck, der *nicht* in einer Zeichenklasse steht, wird ignoriert.
Das bedeutet, dass ein Ausdruck wie "dog | cat" dem schlechter
lesbaren "dog|cat" entspricht, "[a b]" aber weiterhin auf die Zeichen
"'a'", "'b'" oder ein Leerzeichen passt.  Darüber hinaus kannst du
Kommentare in einen RE schreiben; Kommentare reichen von einem
"#"-Zeichen bis zum nächsten Zeilenumbruch.  Zusammen mit dreifach
begrenzten Zeichenketten lassen sich REs damit ordentlicher
formatieren:

   pat = re.compile(r"""
    \s*                 # Skip leading whitespace
    (?P<header>[^:]+)   # Header name
    \s* :               # Whitespace, and a colon
    (?P<value>.*?)      # The header's value -- *? used to
                        # lose the following trailing whitespace
    \s*$                # Trailing whitespace to end-of-line
   """, re.VERBOSE)

Das ist weit besser lesbar als:

   pat = re.compile(r"\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$")


Rückmeldung
===========

Reguläre Ausdrücke sind ein kompliziertes Thema.  Hat dir dieses
Dokument geholfen, sie zu verstehen?  Gab es Stellen, die unklar
waren, oder Probleme, auf die du gestoßen bist und die hier nicht
behandelt werden? Wenn ja, schicke Verbesserungsvorschläge bitte an
den Issue-Tracker.

Das vollständigste Buch über reguläre Ausdrücke ist mit großer
Sicherheit Jeffrey Friedls „Mastering Regular Expressions“, erschienen
bei O'Reilly. Leider widmet es sich ausschließlich den Spielarten
regulärer Ausdrücke in Perl und Java und enthält überhaupt kein
Python-Material. Als Referenz für das Programmieren in Python ist es
daher nicht brauchbar.  (Die erste Auflage behandelte Pythons
inzwischen entferntes Modul "regex", was dir kaum hilft.)  Leih es dir
vielleicht in deiner Bibliothek aus.
