Informationen zu regulären Python-Ausdrücken. Bis jetzt habe ich gegoogelt und nachgeforscht und bei Bedarf implementiert, aber ich dachte, es sei Zeit, mein Verständnis zu vertiefen. Es wird gesagt, dass es großartig zu sein scheint, "bei Bedarf zu suchen und zu implementieren", aber es ist ein Anfängerlevel. Ich schreibe mit dem Bewusstsein, ** was Anfänger von Grund auf lernen sollten ** und ** was der gelegentliche Benutzer neu lernen wird **. In diesem Artikel Knock 100-Sprachverarbeitung 2015 ["Kapitel 3: Reguläre Ausdrücke"](http://www.cl. ecei.tohoku.ac.jp/nlp100/#ch3) ist organisiert.
Verknüpfung | Bemerkungen |
---|---|
Regulärer Ausdruck HOWTO | Python offizieller regulärer Ausdruck How To |
re ---Operation mit regulären Ausdrücken | Python offizielle Re-Paketbeschreibung |
Python verwendet Package re
, um reguläre Ausdrücke zu implementieren. In den folgenden Python-Anweisungen wird "import re" weggelassen.
import re
Verwenden Sie Funktionen wie "re.match" und "re".
#Das erste Argument ist ein Muster für reguläre Ausdrücke(Suchbegriff)Das zweite Argument ist das Suchziel
result = re.match('Hel', 'Hellow python')
print(result)
# <_sre.SRE_Match object; span=(0, 3), match='Hel'>
print(result.group())
# Hel
Verwenden Sie nach dem Kompilieren des Musters für reguläre Ausdrücke Funktionen wie "match" und "sub".
#Kompilieren Sie das Muster für reguläre Ausdrücke im Voraus
regex = re.compile('Hel')
result = regex.match('Hellow python')
print(result)
# <_sre.SRE_Match object; span=(0, 3), match='Hel'>
print(result.group())
# Hel
** Wenn Sie mehrere Muster für reguläre Ausdrücke mehrmals verwenden möchten, verwenden Sie die Kompilierungsmethode **. Offiziell hat die folgende Beschreibung.
Es ist effizienter, re.compile () zu verwenden, um das resultierende kanonische Ausdrucksobjekt zu speichern und wiederzuverwenden, wenn dieser Ausdruck mehrmals in einem Programm verwendet wird. Die neuesten Muster, die an die Matching-Funktionen re.compile () und Module übergeben wurden, werden beim Kompilieren zwischengespeichert, sodass Programme, die jeweils nur wenige reguläre Ausdrücke verwenden, keine regulären Ausdrücke kompilieren müssen.
Wenn Sie dasselbe Muster für reguläre Ausdrücke mehrmals verwenden, scheint das Kompilieren keinen Geschwindigkeitsvorteil zu haben. Ich habe nicht überprüft, wie viel es zwischengespeichert ist.
Die Rohzeichenfolge ist kein spezifisches Thema für reguläre Ausdrücke, kann jedoch zum ** Deaktivieren von Escape-Sequenzen ** verwendet werden.
Im ersteren Fall des folgenden Beispiels wird "\ t" zu einem Tabulator und "\ n" zu einer "Bruchlinie", im letzteren Fall wird es jedoch als "\ t", "\ n" Zeichenfolge behandelt.
print('a\tb\nA\tB')
print(r'a\tb\nA\tB')
Ergebnis der Terminalausgabe
a b
A B
a\tb\nA\tB
** Ich möchte keine Escape-Sequenz für Backslashes im Muster für reguläre Ausdrücke schreiben, daher verwende ich eine rohe Zeichenfolge **
result = re.match(r'\d', '329')
Artikel "Schreiben regulärer Ausdrücke mit rohen Python-Zeichenfolgen" und "Escape-Sequenzen in Python ignorieren (deaktivieren)" Raw string " enthält eine ausführliche Erklärung.
Sie können Zeilenumbrüche in Ihrem Muster für reguläre Ausdrücke verwenden, indem Sie sie in dreifache Anführungszeichen setzen (die "" "" sein können) (keine Unterbrechungen sind in Ordnung).
Sie können Leerzeichen und Kommentare von Mustern für reguläre Ausdrücke ausschließen, indem Sie "re.VERBOSE" übergeben.
** Ripple-Anführungszeichen und re.VERBOSE
machen es sehr lesbar **
Es ist leicht zu erkennen, ob Sie das folgende Muster für reguläre Ausdrücke schreiben.
a = re.compile(r'''\d + # the integral part
\. # the decimal point
\d * # some fractional digits''', re.VERBOSE)
Weitere Informationen zu dreifachen Anführungszeichen finden Sie im Artikel "Generieren von Zeichenfolgen in Python (Anführungszeichen, str-Konstruktoren)" (https://note.nkmk.me/python-str-literal-constructor/).
Übrigens, wenn Sie mehrere Kompilierungsflags im compile
parameter flags
verwenden möchten, können Sie einfach+
(Addition) hinzufügen.
a = re.compile(r'''\d''', re.VERBOSE+re.MULTILINE)
Brief | Erläuterung | Bemerkungen | Beispiel | Spiel | Stimmt nicht überein |
---|---|---|---|---|---|
\d | Zahlen | [0-9]Gleich wie | |||
\D | Andere als Zahlen | [^0-9]Gleich wie | |||
\s | Leerer Charakter | [\t\n\r\f\v]Gleich wie | |||
\S | Andere als weiße Zeichen | [^\t\n\r\f\v]Gleich wie | |||
\w | Alphabet und unterstreichen | [a-zA-Z0-9_]Gleich wie | |||
\W | Nicht alphabetische Zeichen | [\a-zA-Z0-9_]Gleich wie | |||
\A | Der Anfang der Zeichenfolge | ^Ähnlich zu | |||
\Z | Ende der Zeichenfolge | $Ähnlich zu | |||
\b | Wortgrenzen(Raum) | ||||
. | Jeder einzelne Buchstabe | - | 1.3 | 123, 133 | 1223 |
^ | Der Anfang der Zeichenfolge | - | ^123 | 1234 | 0123 |
$ | Ende der Zeichenfolge | - | 123$ | 0123 | 1234 |
* | Wiederholen Sie 0 oder mehrmals | - | 12* | 1, 12, 122 | 11, 22 |
+ | Ein- oder mehrmals wiederholen | - | 12+ | 12, 122 | 1, 11, 22 |
? | 0 mal oder 1 mal | - | 12? | 1, 12 | 122 |
{m} | M-mal wiederholen | - | 1{3} | 111 | 11, 1111 |
{m,n} | Wiederholen Sie m ~ n mal | - | 1{2, 3} | 11, 111 | 1, 1111 |
[] | einstellen | [^5]Dann anders als 5 | [1-3] | 1, 2, 3 | 4, 5 |
| | Summensatz(or) | - | 1|2 | 1, 2 | 3 |
() | Gruppierung | - | (12)+ | 12, 1212 | 1, 123 |
Ich benutze oft die folgenden Funktionen.
Funktion | Zweck |
---|---|
match | Von der SaiteAm AnfangBestimmen Sie, ob es mit dem regulären Ausdruck übereinstimmt |
search | Finden Sie heraus, wo der reguläre Ausdruck übereinstimmt |
findall | Findet alle übereinstimmenden Teilzeichenfolgen und gibt sie als Liste zurück |
sub | String-Ersatz |
Re.match
stimmt nur am Anfang der Zeichenfolge überein, und re.search
stimmt unabhängig von der Position in der Zeichenfolge überein. Weitere Informationen finden Sie unter Offizielle "search () vs. match ()". Beide geben nur das erste Muster zurück (keine Übereinstimmungen nach dem zweiten).
>>> re.match("c", "abcdef") #Der Anfang ist"c"Stimmt nicht überein, weil es nicht ist
>>> re.search("c", "abcdef") #Spiel
<re.Match object; span=(2, 3), match='c'>
Das Ergebnis ist in "Gruppe". Alle Ergebnisse sind in "Gruppe (0)" enthalten, und die gruppierten Suchergebnisse sind fortlaufend von 1 nummeriert.
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0) # The entire match
'Isaac Newton'
>>> m.group(1) # The first parenthesized subgroup.
'Isaac'
>>> m.group(2) # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2) # Multiple arguments give us a tuple.
('Isaac', 'Newton')
findall Findall gibt alle Zeichenfolgen zurück, die dem Muster im Listenformat entsprechen.
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']
Sie können das Erfassungsziel mit ()
angeben. Wenn Sie jedoch mehr als ein Ziel angeben, sieht es wie folgt aus. Es wird als Taple für jede Gruppe zurückgegeben.
>>> print(re.findall(r'''(1st)(2nd)''', '1st2nd1st2nd'))
[('1st', '2nd'), ('1st', '2nd')]
sub Zeichen ersetzen. Die Reihenfolge der Argumente ist 1. Muster für reguläre Ausdrücke, 2. Ersatzzeichenfolge und 3. Ersatzzielzeichenfolge.
>>> re.sub(r'Vor dem Austausch', 'Nach dem Austausch', 'Vor dem Austausch 対象外 Vor dem Austausch')
'Nach dem Austausch Nicht zutreffend Nach dem Austausch'
Im Folgenden sind die häufig verwendeten Kompilierungsflags aufgeführt. Übergeben Sie es an den Funktionsparameter flags
.
Flagge | Bedeutung |
---|---|
DOTALL | . Zu jedem Zeichen einschließlich Zeilenumbrüchen |
IGNORECASE | Groß- und Kleinschreibung wird nicht berücksichtigt |
MULTILINE | ^ Oder$ Stimmt mit mehrzeiligen Zeichenketten überein. |
VERBOSE | Ignorieren Sie Kommentare und Leerzeichen in regulären Ausdrücken |
Ich werde es etwas ausführlicher erklären, mit Ausnahme der VERBOSE und derjenigen, die schwer zu verstehen sind.
DOTALL
re.DOTALL ist eine Option, um einen Zeilenumbruch für den Platzhalter .
(DOT) einzufügen.
string = r'''\
1. Zeile
2. Zeile am Zeilenanfang'''
print(re.findall(r'1st.*2nd', string, re.DOTALL))
# ['1st line\n Zeile ab dem 2. Platz']
print(re.findall(r'1st.*2nd', string))
# No Match
Weitere Informationen finden Sie im Artikel Python: Ersetzen des mehrzeiligen Abgleichs durch reguläre Ausdrücke.
MULTILINE Verwenden Sie diese Option, wenn Sie nach mehreren Zeilen suchen möchten. Wenn Sie im folgenden Beispiel "re.MULTILINE" verwenden, ist auch die zweite Zeile ("der Anfang der zweiten Zeile") das Ziel. * Bei der Funktion "match" ist die Verwendung von "re.MULTILINE" nicht sinnvoll.
string = r'''\
1. Zeile
2. Zeile am Zeilenanfang'''
print(re.findall(r'^Zeilenanfang.*', string, re.MULTILINE))
# ['1. Zeile', '2. Zeile am Zeilenanfang']
print(re.findall(r'^Zeilenanfang.*', string))
# ['1. Zeile']
Weitere Informationen finden Sie im Artikel Python: Ersetzen mehrzeiliger Übereinstimmungen durch reguläre Ausdrücke.
Tips
Wenn Sie "(?: ...)" hinzufügen, wird es nicht in die Suchergebniszeichenfolge ** aufgenommen und nicht erfasst. Die offizielle Syntax für reguläre Ausdrücke erklärt Folgendes.
Eine nicht erfasste Version regulärer Klammern. Entspricht einem regulären Ausdruck in Klammern, aber die von dieser Gruppe übereinstimmenden Teilzeichenfolgen können nicht abgerufen werden, nachdem die Übereinstimmung durchgeführt oder später im Muster referenziert wurde.
Im folgenden Beispiel wird der Teil "4" als Muster für reguläre Ausdrücke verwendet, jedoch nicht im Ergebnis ausgegeben.
>>> re.findall(r'(.012)(?:4)', 'A0123 B0124 C0123')
['B012']
** Sie können die Länge der Zielzeichenfolge des Suchergebnisses steuern **. ** Eine gierige Übereinstimmung ist eine Übereinstimmung mit der maximalen Länge, und eine nicht gierige Übereinstimmung ist eine Übereinstimmung mit der minimalen Länge. Die Standardeinstellung ist "Gierige Übereinstimmung". Um eine nicht gierige Übereinstimmung zu erzielen, fügen Sie "?" An fortlaufende Sonderzeichen ("*,?, +") An. Unten sind Beispielsätze von beiden.
#Gieriges Match
>>> print(re.findall(r'.0.*2', 'A0123 B0123'))
['A0123 B012']
#Nicht gieriges Match(*Nach dem?)
>>> print(re.findall(r'.0.*?2', 'A0123 B0123'))
['A012', 'B012']
Weitere Informationen finden Sie im Artikel "Gierige und nicht gierige Übereinstimmungen".
Sie können \ number
verwenden, um den Inhalt der vorherigen Gruppe abzugleichen. In Offizielle Syntax die folgende Beschreibung.
Entspricht dem Inhalt der Gruppe mit derselben Nummer. Gruppen können beginnend mit 1 nummeriert werden. Zum Beispiel stimmt (. +) \ 1 mit dem 'oder '55 55' überein, aber nicht mit dem '(beachten Sie das Leerzeichen nach der Gruppe). Diese spezielle Sequenz kann nur verwendet werden, um eine der ersten 99 Gruppen abzugleichen. Wenn die erste Ziffer der Zahl 0 ist oder die Zahl eine dreistellige Oktadezimalzahl ist, wird sie als Zeichen mit der Oktadezimalwertzahl interpretiert, nicht als Gruppenübereinstimmung. Alle numerischen Escapezeichen zwischen den Zeichenklassen '[' und ']' werden als Zeichen behandelt.
Insbesondere entspricht der Teil "\ 1" dem abcab in derselben Bedeutung wie der Teil, der mit dem vorherigen "(ab)" übereinstimmt, aber abddd hat nicht das 4. und 5. Zeichen ab. Stimmt nicht überein.
>>> print(re.findall(r'''(ab).\1''', 'abcab abddd'))
['ab']
Obwohl es nicht im Übereinstimmungsziel enthalten ist, gibt es die folgenden vier Möglichkeiten, um die Zeichenfolge in die Suchbedingung aufzunehmen oder nicht aufzunehmen.
Die folgende Form wird als Matrix verwendet.
positiv | Verweigerung | |
---|---|---|
Schau voraus | (?=...) ... Übereinstimmung, wenn der Teil als nächstes fortgesetzt wird |
(?!...) ... Übereinstimmung, wenn das Teil nicht folgt |
Schau voraus | (?<=...) ... Übereinstimmung, wenn sich das Teil vor der aktuellen Position befindet und eine Übereinstimmung vorliegt |
(?<!...) ... Übereinstimmung, wenn sich das Teil vor der aktuellen Position befindet und keine Übereinstimmung vorliegt |
Ein konkretes Beispiel ist leichter zu verstehen als eine ausführliche Erklärung.
>>> string = 'A01234 B91235 C01234'
#Bejahende Vorausschau(Positive Lookahead Assertions)
# '123'Neben an'5'Zeichenkette gefolgt von('(?=5)'Teil ist der folgende'.'Nicht ohne kommen)
>>> print(re.findall(r'..123(?=5).', string))
['B91235']
#Negative Vorausschau-Behauptung(Negative Lookahead Assertions)
# '123'Neben an'5'Zeichenfolge, die nicht folgt('(?!5)'Teil ist der folgende'.'Nicht ohne kommen)
>>> print(re.findall(r'..123(?!5).', string))
['A01234', 'C01234']
#Bejahende Vorausschau(Positive Lookbehind Assertions)
# '0'Aber'123'Passende Zeichenfolge vor('(?<=0)'Der Teil von ist der Anfang'.'Aberなければ取得しない)
>>> print(re.findall(r'..(?<=0)123', string))
['A0123', 'C0123']
#Negative Vorausschau-Behauptung(Negative Lookbehind Assertions)
# '0'Aber'123'Nicht übereinstimmender String zuvor('(?<!0)'Der Teil von ist der Anfang'.'Aberなければ取得しない)
>>> print(re.findall(r'..(?<!0)123', string))
['B9123']
Recommended Posts