Heim  >  Artikel  >  Backend-Entwicklung  >  Eine detailliertere Anleitung zu Python-Operationen mit regulären Ausdrücken

Eine detailliertere Anleitung zu Python-Operationen mit regulären Ausdrücken

巴扎黑
巴扎黑Original
2017-05-21 11:16:381607Durchsuche

Python hat seit Version 1.5 das re-Modul hinzugefügt, das Muster für reguläre Ausdrücke im Perl-Stil bereitstellt. Versionen vor Python 1.5 stellten über das Regex-Modul Muster im Emecs-Stil bereit. Der Emacs-Stilmodus ist etwas weniger lesbar und weniger leistungsfähig. Versuchen Sie daher, das Regex-Modul nicht zu verwenden, wenn Sie neuen Code schreiben. Natürlich können Sie gelegentlich noch Spuren davon in altem Code finden.

Reguläre Ausdrücke (oder RE) sind ihrer Natur nach eine kleine, hochspezialisierte Programmiersprache, die in Python eingebettet und durch das re-Modul implementiert wird. Mit dieser kleinen Sprache können Sie Regeln für einen entsprechenden Satz von Zeichenfolgen angeben, die Sie abgleichen möchten. Dieser Satz von Zeichenfolgen kann englische Sätze, E-Mail-Adressen, TeX-Befehle oder was auch immer enthalten. Sie können dann Fragen stellen wie „Entspricht diese Zeichenfolge dem Muster?“ oder „Entspricht ein Teil dieser Zeichenfolge dem Muster?“. Sie können RE auch verwenden, um Zeichenfolgen auf verschiedene Weise zu ändern oder aufzuteilen.


Muster regulärer Ausdrücke werden in einer Reihe von Bytecodes kompiliert und dann von einer in C geschriebenen Matching-Engine ausgeführt. Bei fortgeschrittener Verwendung sollte man möglicherweise auch sorgfältig darauf achten, wie die Engine ein bestimmtes RE ausführt und wie das RE auf eine bestimmte Art und Weise geschrieben wird, um die Ausführung des erzeugten Bytecodes zu beschleunigen. In diesem Artikel geht es nicht um die Optimierung, da Sie dafür die internen Mechanismen der Matching-Engine vollständig verstehen müssen.


Die Sprache für reguläre Ausdrücke ist relativ klein und eingeschränkt (eingeschränkte Funktionalität), sodass nicht die gesamte Zeichenfolgenverarbeitung mit regulären Ausdrücken durchgeführt werden kann. Natürlich gibt es einige Aufgaben, die mit regulären Ausdrücken erledigt werden können, aber am Ende werden die Ausdrücke äußerst komplex. Wenn Sie auf solche Situationen stoßen, ist es möglicherweise besser, Python-Code zu schreiben, um damit umzugehen. Obwohl Python-Code langsamer ist als ein ausgefallener regulärer Ausdruck, ist er einfacher zu verstehen.

Einfacher Modus

Wir beginnen mit dem einfachsten Erlernen regulärer Ausdrücke. Da reguläre Ausdrücke häufig zur Zeichenfolgenmanipulation verwendet werden, beginnen wir mit der häufigsten Aufgabe: dem Zeichenabgleich.


Eine detaillierte Erklärung der Informatik, die regulären Ausdrücken (deterministische und nichtdeterministische endliche Automaten) zugrunde liegt, finden Sie in jedem Lehrbuch zum Schreiben von Compilern.

Zeichenübereinstimmung

Die meisten Buchstaben und Zeichen stimmen im Allgemeinen überein. Beispielsweise stimmt der reguläre Ausdruck test genau mit der Zeichenfolge „test“ überein. (Sie können auch den Modus ohne Berücksichtigung der Groß- und Kleinschreibung verwenden, wodurch dieser RE auch mit „Test“ oder „TEST“ übereinstimmt; mehr dazu später.)

Natürlich gibt es Ausnahmen von dieser Regel, einige Zeichen sind ziemlich speziell , sie stimmen nicht mit sich selbst überein, sondern weisen darauf hin, dass sie mit etwas Besonderem übereinstimmen sollten, da sie sonst die Anzahl der Wiederholungen anderer Teile des RE beeinflussen. Ein großer Abschnitt dieses Artikels ist der Diskussion verschiedener Metazeichen und ihrer Funktionen gewidmet.

Hier finden Sie eine vollständige Liste der Metazeichen. Ihre Bedeutung wird im weiteren Verlauf dieses Handbuchs erläutert.

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

Die Metazeichen, die wir zuerst untersuchen, sind „[“ und „]“. Sie werden häufig verwendet, um eine Zeichenkategorie anzugeben, also einen Zeichensatz, den Sie abgleichen möchten. Zeichen können einzeln aufgelistet werden, oder zwei durch ein „-“-Zeichen getrennte bestimmte Zeichen können zur Darstellung eines Zeichenbereichs verwendet werden. Beispielsweise stimmt [abc] mit jedem Zeichen unter „a“, „b“ oder „c“ überein. Sie können auch das Intervall [a-c] verwenden, um denselben Zeichensatz darzustellen, was den gleichen Effekt wie ersteres hat. Wenn Sie nur Kleinbuchstaben abgleichen möchten, sollte RE als [a-z] geschrieben werden. Das Metazeichen

funktioniert nicht in Kategorien. Beispielsweise entspricht [akm$] jedem der Zeichen „a“, „k“, „m“ oder „$“; „$“ wird normalerweise als Metazeichen verwendet, seine Eigenschaften werden jedoch innerhalb der Zeichenklasse entfernt , Rückkehr zu normalen Zeichen.

Sie können die Ergänzung verwenden, um Zeichen zuzuordnen, die nicht im Bereich liegen. Die Methode besteht darin, „^“ als erstes Zeichen der Kategorie zu verwenden; „^“ an anderer Stelle entspricht einfach dem „^“-Zeichen selbst. Beispielsweise entspricht [^5] jedem Zeichen außer „5“.

Das vielleicht wichtigste Metazeichen ist der Backslash „“. Als String-Buchstabe in Python können nach dem Backslash verschiedene Zeichen hinzugefügt werden, um unterschiedliche Sonderbedeutungen auszudrücken. Es kann auch verwendet werden, um alle Metazeichen zu löschen. Zeichen, damit Sie können sie in einem Muster zuordnen. Wenn Sie beispielsweise die Zeichen „[“ oder „““ zuordnen müssen, können Sie ihnen einen Backslash voranstellen, um ihre besondere Bedeutung zu entfernen: „[ oder „“.

Einige vordefinierte Zeichensätze, die durch Sonderzeichen dargestellt werden, die mit „“ beginnen, sind normalerweise nützlich, z. B. Ziffern, Buchstaben oder andere nicht leere Zeichensätze. Im Folgenden sind die verfügbaren voreingestellten Sonderzeichen aufgeführt:

# !python

>>> importieren re

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

>>> print p

<re.RegexObject-Instanz bei 80b4150>

re.compile() akzeptiert auch optionale Flag-Parameter, die häufig zum Implementieren verschiedener Sonderfunktionen und Syntaxänderungen verwendet werden. Wir werden uns später alle verfügbaren Einstellungen ansehen, aber zunächst nur ein Beispiel:

#!python

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

RE wird als String an re.compile() gesendet. REs werden als Zeichenfolgen verarbeitet, da reguläre Ausdrücke kein zentraler Bestandteil der Python-Sprache sind und keine spezielle Syntax für sie erstellt wurde. (Anwendungen benötigen einfach keine REs, daher besteht keine Notwendigkeit, die Sprachspezifikation durch deren Einbindung aufzublähen.) Das re-Modul ist einfach als C-Erweiterungsmodul in Python eingebunden, genau wie die socket- oder zlib-Module.


Verwenden Sie REs als Strings, um die Einfachheit der Python-Sprache sicherzustellen. Dies führt jedoch zu Problemen, wie im Titel des nächsten Abschnitts erwähnt.

Backslash-Probleme

In früheren Vorschriften verwendeten reguläre Ausdrücke das Backslash-Zeichen („“), um eine spezielle Formatierung anzugeben oder die Verwendung eines Sonderzeichens zu ermöglichen, ohne dessen besondere Verwendung aufzurufen. Dies führt zu Konflikten mit Pythons Verwendung derselben Zeichen in Zeichenfolgen


Nehmen wir an, Sie möchten ein RE schreiben, das mit der Zeichenfolge „“section“ übereinstimmt“, die wahrscheinlich in einer LATEX-Datei sucht. Um den Programmcode zu beurteilen, schreiben Sie zunächst die Zeichenfolge, mit der Sie übereinstimmen möchten. Als nächstes müssen Sie allen Backslashes und Metazeichen einen Backslash voranstellen, um ihre besondere Bedeutung zu entfernen.

字符 阶段
section 要匹配的字符串
\section 为 re.compile 取消反斜杠的特殊意义
"\section" 为字符串取消反斜杠


Einfach ausgedrückt: Um einen Backslash zuzuordnen, müssen Sie „\“ in die RE-Zeichenfolge schreiben, da der reguläre Ausdruck „\“ sein muss und alle Backslash-Balken „\“ sein müssen wird gemäß der Konvention der Python-Zeichenfolgen-Buchstaben-Darstellung als „\“ dargestellt. Diese sich wiederholende Natur von Backslashes in REs führt zu einer großen Anzahl wiederholter Backslashes und die resultierenden Zeichenfolgen sind schwer zu verstehen.


Die Lösung besteht darin, die rohe String-Darstellung von Python für reguläre Ausdrücke zu verwenden; das Hinzufügen eines „r“-Backslashs, bevor der String nicht auf besondere Weise verarbeitet wird, sodass r“n“ aus zwei Zeichen besteht, die „ " und „n“ und „n“ ist ein Zeichen, das eine neue Zeile darstellt. Reguläre Ausdrücke werden im Python-Code normalerweise durch diese Rohzeichenfolge dargestellt.

常规字符串 Raw 字符串
"ab*" r"ab*"
"\section" r"\section"
"\w+\s+" r"w+s+1"

Abgleich durchführen

Was machen Sie damit, wenn Sie ein kompiliertes reguläres Ausdrucksobjekt haben? „RegexObject“-Instanzen verfügen über einige Methoden und Eigenschaften. Hier werden nur die wichtigsten angezeigt. Wenn Sie die vollständige Liste sehen möchten, konsultieren Sie bitte die Python-Bibliotheksreferenz

方法/属性 作用
match() 决定 RE 是否在字符串刚开始的位置匹配
search() 扫描字符串,找到这个 RE 匹配的位置
findall() 找到 RE 匹配的所有子串,并把它们作为一个列表返回
finditer() 找到 RE 匹配的所有子串,并把它们作为一个迭代器返回


Wenn keine Übereinstimmung gefunden wird, geben match() und search() None zurück. Bei Erfolg wird eine „MatchObject“-Instanz zurückgegeben, die Informationen über die Übereinstimmung enthält: wo sie beginnt und endet, den Teilstring, mit dem sie übereinstimmte, usw.

Sie können es lernen, indem Sie den Mensch-Maschine-Dialog nutzen und mit dem Re-Modul experimentieren. Wenn Sie Tkinter haben, sollten Sie einen Blick auf Tools/scripts/redemo.py werfen, ein Demoprogramm, das in der Python-Distribution enthalten ist.

Führen Sie zunächst den Python-Interpreter aus, importieren Sie das re-Modul und kompilieren Sie ein RE:

#!python

Python
2.2.2 (#1, 10. Februar 2003, 12:57:01)

>>> importieren re

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

>>> p

<_sre.SRE_Pattern-Objekt bei 80c3c28>


Jetzt können Sie versuchen, es zu verwenden RE [a-z]+, um verschiedene Zeichenfolgen abzugleichen. Eine leere Zeichenfolge wird überhaupt nicht übereinstimmen, da + „eine oder mehrere Wiederholungen“ bedeutet. In diesem Fall gibt match() None zurück, da der Interpreter dadurch keine Ausgabe erhält. Sie können dies herausfinden, indem Sie das Ergebnis von match() explizit ausdrucken.

# !python

>>> p.match("")

>>> drucken p.match ("")

Keine

Nun versuchen wir, es zu verwenden, um eine Zeichenfolge wie „ tempo anzupassen ". In diesem Fall gibt match() ein MatchObject zurück. So können Sie das Ergebnis zur späteren Verwendung in einer Variablen speichern.

# !python

>>> m =p.match('tempo')

>> > >>Jetzt können Sie „MatchObject“ nach zugehörigen Informationen zu übereinstimmenden Zeichenfolgen abfragen. MatchObject-Instanzen verfügen außerdem über mehrere Methoden und Eigenschaften; die wichtigsten sind wie folgt:


Probieren Sie diese Methoden aus und Sie werden bald ihre Auswirkungen verstehen:

#!python

> >m.group()

'tempo'

>>> m.start(), m.end()

(0,
5 )

>>> m.span()

(0,
5)

group() gibt die mit RE übereinstimmende Teilzeichenfolge zurück. start() und end() geben den Index zurück, an dem die Übereinstimmung beginnt und endet. span() gibt die Start- und Endindizes zusammen in einem einzigen Tupel zurück. Denn die Match-Methode prüft, ob start() immer Null ist, wenn RE mit dem Abgleich am Anfang der Zeichenfolge beginnt. Die Suchmethode einer „RegexObject“-Instanz scannt jedoch die folgende Zeichenfolge. In diesem Fall beginnt die Übereinstimmung möglicherweise an einer anderen Position als Null.

# !python

>>> drucken p.match('::: message')

Keine

>>> m = p.search('::: Nachricht') ; drucken m

<re.MatchObject-Instanz bei 80c9650>

>>> m. group()

'message'

> >>m.span()

(
4, 11)

In tatsächlichen Programmen besteht der häufigste Ansatz darin, „MatchObject“ in einer Variablen zu speichern und dann zu prüfen, ob es None ist, normalerweise wie folgt:

# !python

p
= re.compile( )

m
= p.match( 'string goes here' )

if m:

print 'Match gefunden: ', m.group()

else:

drucken 'Keine Übereinstimmung'

Zwei `RegexObject`-Methoden Gibt zurück alle Teilzeichenfolgen, die dem Muster entsprechen. findall() gibt eine Liste übereinstimmender Zeichenfolgenzeilen zurück:

#!python

>>> p = re.compile('" d+')

>>> p.findall(' 12 Trommler trommeln, 11 Pfeifer pfeifen, 10 Lords springen')

[
' 12', '11', '10']

findall() musste eine Liste erstellen, als es das Ergebnis in Python 2.2 zurückgab. , können Sie auch die finditer()-Methode

verwenden.

# !python

>>> iterator = p.finditer('12 Schlagzeuger trommeln, 11  10 ')

>>> iterator

<aufrufbar-Iteratorobjekt bei 0x401833ac>

>>> for match in iterator:

     
print  match.span()



(0, 
2)

(
2224)

(
2931)

模块级函数

你不一定要产生一个 `RegexObject`. 对象然後再调用它的方法;re 模块也提供了顶级函数调用如 match()、search()、sub() 等等。这些函数使用 RE Die `RegexObject`-Funktion ist nicht verfügbar要么是 None 要么就是一个 `MatchObject` 的实例.

#!python

>>>  print re.match(r'From"s+''Fromage amk')

Keine

> ;>> re.match(r'From"s+''Von amk Do 14 Mai 19:12:10 1998')

<re.MatchObject instance bei 80c5978>

Unter der Haube generieren diese Funktionen einfach ein RegexOject und rufen die entsprechenden Methoden darauf auf. Außerdem speichern sie kompilierte Objekte im Cache, sodass zukünftige Aufrufe mit demselben RE schneller erfolgen.


Werden Sie diese Funktionen auf Modulebene verwenden oder zuerst ein „RegexObject“ erhalten und dann seine Methoden aufrufen? Welche Sie wählen, hängt davon ab, wie effizient Sie mit RE umgehen und von Ihrem persönlichen Codierungsstil. Wenn ein RE nur einmal im Code verwendet wird, sind Funktionen auf Modulebene möglicherweise praktischer. Wenn das Programm viele reguläre Ausdrücke enthält oder denselben an mehreren Stellen wiederverwendet, ist es sinnvoller, alle Definitionen zusammenzufassen und alle REs vorab in einem Codeblock zu kompilieren. Schauen Sie sich ein Beispiel aus der Standardbibliothek an, extrahiert aus der Datei xmllib.py:

#!python

ref
= re.compile( )

entityref
= re.compile( )

charref
= re.compile( )

starttagopen
= re.compile( )

Normalerweise bevorzuge ich die Verwendung kompilierter Objekte, auch wenn sie nur einmal verwendet werden, aber nur wenige Menschen werden in dieser Hinsicht so puristisch sein wie ich.

Kompilierungsflags

Mit Kompilierungsflags können Sie die Art und Weise, wie reguläre Ausdrücke ausgeführt werden, teilweise ändern. Im re-Modul kann das Flag zwei Namen verwenden, einer ist der vollständige Name, z. B. IGNORECASE, und der andere ist die Abkürzung in Ein-Buchstaben-Form, z. B. I. (Wenn Sie mit der Modusänderung von Perl vertraut sind, verwenden die Ein-Buchstaben-Formulare denselben Buchstaben; die Abkürzung für re.VERBOSE lautet beispielsweise re.X.) Mehrere Flags können durch bitweise ODER-Verknüpfung angegeben werden. Beispielsweise ist re.I |. re.M auf die Flags I und M gesetzt:


Hier ist eine Tabelle der verfügbaren Flags mit detaillierten Beschreibungen hinter jedem Flag.

标志 含义
DOTALL, S 使 . 匹配包括换行在内的所有字符
IGNORECASE, I 使匹配对大小写不敏感
LOCALE, L 做本地化识别(locale-aware)匹配
MULTILINE, M 多行匹配,影响 ^ 和 $
VERBOSE, X 能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂

I
IGNORECASE

sorgt dafür, dass bei der Übereinstimmung von Zeichenklassen und Zeichenfolgen die Groß-/Kleinschreibung beim Abgleichen von Buchstaben ignoriert wird. Beispielsweise kann [A-Z] auch mit Kleinbuchstaben übereinstimmen, und „Spam“ kann mit „Spam“, „spam“ oder „spAM“ übereinstimmen. Dieser Kleinbuchstabe berücksichtigt nicht die aktuelle Position.

L
LOKALE

Wirkt sich auf „w“, „W“, „b“ und „B“ aus, abhängig von der aktuellen Lokalisierungseinstellung .

locales ist eine Funktion in der C-Bibliothek, die zur Unterstützung der Programmierung verwendet wird, wenn verschiedene Sprachen berücksichtigt werden müssen. Wenn Sie beispielsweise mit französischem Text arbeiten, möchten Sie „w+“ verwenden, um Text abzugleichen, aber „w“ stimmt nur mit der Zeichenklasse [A-Za-z] überein; es stimmt nicht mit „é“ oder „ç“ überein ". Wenn Ihr System entsprechend konfiguriert ist und das Gebietsschema auf Französisch eingestellt ist, teilt eine interne C-Funktion dem Programm mit, dass „é“ auch als Buchstabe betrachtet werden soll. Die Verwendung des LOCALE-Flags beim Kompilieren eines regulären Ausdrucks führt zu einem kompilierten Objekt, das diese C-Funktionen zur Verarbeitung von „w“ verwendet. Dies ist zwar langsamer, ermöglicht Ihnen aber dennoch die Verwendung von „w+“, um französischen Text abzugleichen, wie Sie möchten.

M
MULTILINE


(^ und $ werden zu diesem Zeitpunkt nicht interpretiert; sie werden in Abschnitt eingeführt 4.1 .)


Verwenden Sie „^“, um nur den Anfang der Zeichenfolge abzugleichen, während $ nur das Ende der Zeichenfolge und das Ende der Zeichenfolge unmittelbar vor einer neuen Zeile (falls vorhanden) abgleicht ). Wenn dieses Flag angegeben ist, stimmt „^“ mit dem Anfang der Zeichenfolge und dem Anfang jeder Zeile in der Zeichenfolge überein. Ebenso entspricht das Metazeichen $ dem Ende der Zeichenfolge und dem Ende jeder Zeile in der Zeichenfolge (direkt vor jeder neuen Zeile).

S
DOTALL

Stellen Sie sicher, dass das Sonderzeichen „.“ genau mit jedem Zeichen übereinstimmt, einschließlich Zeilenumbrüchen, „. " Entspricht jedem Zeichen außer Newline.

Leicht verständlich. Wenn dieses Flag angegeben ist, werden Leerzeichen innerhalb der RE-Zeichenfolge ignoriert, es sei denn, das Leerzeichen befindet sich innerhalb einer Zeichenklasse oder nach einem Backslash. Dadurch können Sie REs klarer organisieren und einrücken. Sie können damit auch Kommentare in das RE schreiben, die von der Engine ignoriert werden. Kommentare werden mit einem „#“-Symbol gekennzeichnet, dieses Symbol darf jedoch nicht nach einer Zeichenfolge oder einem Backslash stehen.
Als Beispiel sehen Sie hier ein RE mit re.VERBOSE; sehen Sie, wie viel einfacher es ist, es zu lesen?


Code-Hervorhebung erstellt von Actipro CodeHighlighter (Freeware)

http://www.CodeHighlighter.com/


-->

#


#

!python
>>>
print re.search('^From ', 'Von hier in die Ewigkeit')
<
re.MatchObject-Instanz bei 80c1520>
>>> ;
print re.search('^From', 'Rezitieren aus dem Gedächtnis')Keine

$

entspricht dem Ende einer Zeile, das entweder als Ende der Zeichenfolge oder als beliebige Position nach einem Zeilenumbruchzeichen

definiert ist.

# !python

>>> drucken re.search('}$''{block} ')

<re.MatchObject instance at 80adfa8>

>>> drucken re.search('}$''{block} ' )

Keine

>>> drucken re. search('}$''{block}"n')

<re.MatchObject instance at 80adfa8>

匹配一个 "$",使用 "$ 或将其包含在字符类中,如[$]。

"A


只匹配字符串首。当不在 MULTILINE 模式,„A 和 ^ 实际上是一样的。然而,在 MULTILINE只是匹配字符串首,而 ^ 还可以匹配在换行符之後字符串的任何位置.

"Z

Trifft nur am Ende der Zeichenfolge zu.
只匹配字符串尾.

"b

单词边界。这是个零宽界定符(Nullbreitenzusicherungen)只用以匹配单词的用空白符或非字母数字符来标示的.


下面的例子只匹配 „class“ 整个单词;而当它被包含在其他单词中时不匹配.

# !python

>>> p = re.compile(r'"bclass"b')

>>> print p.search('überhaupt keine Klasse')

<re.MatchObject-Instanz bei 80c8f28>

>>> print p.search('der freigegebene Algorithmus')

Keine

>>> print p.search('eine Unterklasse ist')

Keine

Hier gibt es zwei Feinheiten, die Sie bei der Verwendung dieser speziellen Sequenz beachten sollten. Der erste ist der schlimmste Konflikt zwischen Python-Strings und regulären Ausdrücken. In Python-Strings ist „b“ ein Backslash-Zeichen und sein ASCII-Wert ist 8. Wenn Sie keine Rohzeichenfolge verwenden, konvertiert Python „b“ in ein Fallback-Zeichen und Ihr RE wird nicht verwendet in der Lage, es nach Ihren Wünschen anzupassen. Das folgende Beispiel sieht genauso aus wie unser vorheriges RE, jedoch ohne ein „r“ vor der RE-Zeichenfolge.

# !python

>>> p = re.compile('"bclass"b')

> ;>> print p.search('überhaupt keine Klasse')

Keine

>>> drucken p.search('"b' + 'Klasse' + '"b')

<re.MatchObject-Instanz bei 80c3ee0> ;

Der zweite befindet sich in der Zeichenklasse, dieser Qualifizierer (Behauptung) hat keine Auswirkung, „b stellt das Fallback-Zeichen für die Kompatibilität mit Python-Strings dar.

“ B


Eine weitere Behauptung mit der Breite Null, die das Gegenteil von „b“ ist und nur dann zutrifft, wenn die aktuelle Position nicht an einer Wortgrenze liegt. >Gruppe

Sie oft Zum Analysieren von Zeichenfolgen werden häufig mehr Informationen benötigt als nur die Frage, ob der RE übereinstimmt, und ein RFC-822-Header wird in mehrere Gruppen unterteilt und ein Wert durch „:“. Dies kann durch Schreiben eines regulären Ausdrucks erreicht werden, der mit dem gesamten Header übereinstimmt, wobei eine Gruppe mit dem Headernamen übereinstimmt und die andere Gruppe mit dem Header übereinstimmt. Die

-Gruppen sind Die durch die Metazeichen „(“ und „)“ identifizierten Ausdrücke haben in mathematischen Ausdrücken weitgehend die gleiche Bedeutung. Sie können beispielsweise Wiederholungskennzeichen wie *, +, ? verwenden. und {m,n}, um den Inhalt der Gruppe zu wiederholen, z. B. (ab)* entspricht null oder mehr Duplikaten von „ab“.


Code-Hervorhebung erstellt von Actipro CodeHighlighter (Freeware)
#
!python

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

>>>
print p.match('ababababab').span()(0,

10
)

Gruppen werden mit „(“ und „)“ angegeben und erhalten die Start- und Endindizes des Textes, mit dem sie übereinstimmen. Dies kann mit einem Argument mithilfe von group(), start(), end() und span() erfolgen. Abrufen. Die Gruppen werden ab 0 gezählt. Gruppe 0 ist immer vorhanden; es handelt sich um die gesamte RE, daher verwenden alle Methoden von „MatchObject“ Gruppe 0 als Standardargument. Später werden wir sehen, wie man Spans ausdrückt, die den passenden Text nicht erhalten können.

# !python

>>> p = re.compile('(a)b')

>>> m = p.match('ab')

>>> m.group()

'ab'

>>> m.group( 0)

'ab'

Die Gruppe ist von Zählen von links nach rechts, beginnend bei 1. Gruppen können verschachtelt werden. Der Zahlenwert der Zählung lässt sich ermitteln, indem man die Anzahl der offenen Klammern von links nach rechts zählt.

# !python

>>> p = re.compile('(a(b)c)d')

>>> m = p.match('abcd ')

>>> m.group(0)

'abcd'

>>> m.group(1)

'abc'

>>> m.group(2)

'b'

group() kann mehrere Gruppennummern gleichzeitig eingeben In diesem Fall wird ein Tupel zurückgegeben, das die Werte enthält, die diesen Gruppen entsprechen.

# !python

>>> m.group(2,1,2)

(
'b', 'abc', 'b')

Die Methode groups() gibt ein Tupel zurück, das alle Gruppenzeichenfolgen enthält, beginnend mit
1 auf die in enthaltene Gruppennummer.

#!python

>>> ;m.groups()

(
'abc', 'b')

Rückverweise im Muster ermöglichen es Ihnen, den Inhalt eines vorherigen anzugeben Wenn Sie die Gruppe erfassen möchten, muss die Gruppe auch an der aktuellen Position in der Zeichenfolge gefunden werden. Wenn beispielsweise der Inhalt von Gruppe 1 am aktuellen Speicherort gefunden werden kann, ist „1“ erfolgreich, andernfalls schlägt es fehl. Denken Sie daran, dass Python-Strings auch Backslashes zum Hinzufügen von Daten verwenden, damit die Zeichenfolge beliebige Zeichen enthalten kann. Stellen Sie daher sicher, dass dies in RE der Fall ist Verwenden Sie rohe Zeichenfolgen, wenn Sie Rückverweise verwenden. Die folgende RE findet beispielsweise Wortpaare in einer Zeichenfolge, die von Actipro CodeHighlighter (Freeware) erstellt wurde

-->

#

!python

# !python

>>> m = re.match("([abc])+", "abc")

>>> m.groups()

(
'c',)

>> ;> m = re.match("(?:[abc])+", "abc")

>>> m.groups()

()

Zusätzlich zur Erfassung des Inhalts der passenden Gruppe, keine Erfassungsgruppe und Capture Eine Gruppe verhält sich genau gleich; Sie können jedes beliebige Zeichen darin einfügen, Sie können es mit sich wiederholenden Metazeichen wie „*“ wiederholen und Sie können es in anderen Gruppen (nicht erfassende Gruppen und erfassende Gruppen) verschachteln. (?:...) ist besonders nützlich zum Ändern bestehender Gruppen, da Sie eine neue Gruppe hinzufügen können, ohne alle anderen Gruppennummern zu ändern. Es gibt auch keinen Unterschied in der Sucheffizienz zwischen erfassenden und nicht erfassenden Gruppen, keine ist schneller als die andere.


Zweitens ist es wichtiger und leistungsfähiger, Gruppen mit Namen zu spezifizieren, statt sie mit Zahlen anzugeben.


Die Syntax der Befehlsgruppe ist eine der Python-spezifischen Erweiterungen: (?P...). Der Name ist offensichtlich der Name der Gruppe. Eine benannte Gruppe ist dasselbe wie eine einfangende Gruppe, außer dass die Gruppe einen Namen hat. Die Methoden von „MatchObject“ akzeptieren bei der Erfassung von Gruppen entweder eine Ganzzahl, die die Gruppennummer darstellt, oder eine Zeichenfolge, die den Gruppennamen enthält. Benannte Gruppen können auch Zahlen sein, sodass Sie auf zwei Arten Informationen über eine Gruppe erhalten können:

#!python

> >> p = re.compile(r'(?P "b "w+"b)')

>>> m = p.search( '((((Viele Satzzeichen))))' )

>>> m.group('word')

'Lots'

>>>m.group(1)

' Lose '

Benannte Gruppen sind praktisch, da Sie damit leicht zu merkende Namen verwenden können, anstatt sich Zahlen merken zu müssen :

#!python

InternalDate
= re.compile(r' INTERNALDATE "'

r
'(?P [ 123] [0-9])-(?P[A-Z][a-z][a-z])-'

r
'(?P[0-9][0-9][0-9][0-9])'

r
' (?P[0-9][0-9]):(?P[0-9][ 0-9 ]):(?P[0-9][0-9])'

r
' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9] )'

r
'"')

Natürlich ist es viel einfacher, m.group('zonem') zu bekommen, als sich daran zu erinnern, Gruppe 9 zu bekommen.


Aufgrund der Rückreferenzsyntax stellen Ausdrücke wie (...)"1 die Gruppennummer dar. In diesem Fall macht es natürlich einen Unterschied, den Gruppennamen anstelle der Gruppennummer zu verwenden. Ja, das gibt es auch eine Python-Erweiterung: (?P=name), die dafür sorgen kann, dass der Gruppeninhalt namens name an der aktuellen Position wiedergefunden wird. Um wiederholte Wörter zu finden, kann auch der reguläre Ausdruck („b“w+)“s+“1 verwendet werden geschrieben als (?P "b"w+)"s+(?P=word):

#!python

>>> p = re.compile(r'(?P')

>>> p.search('Paris im Frühling').group()

' das'

Vorwärtstrennzeichen

Eine weitere Behauptung mit der Breite Null ist das Vorwärtstrennzeichen. Die Vorwärtstrennzeichen umfassen Positive Vorwärtstrennzeichen und positive Rückwärtstrennzeichen, wie unten gezeigt:

(?=...)

Positive Trennzeichen vorwärts, wenn der enthaltene reguläre Ausdruck durch gekennzeichnet ist ... ist an der aktuellen Position erfolgreich, andernfalls schlägt es fehl, aber sobald der enthaltene Ausdruck ausprobiert wurde, verbessert sich die Matching-Engine überhaupt nicht; 🎜>(?!...)

Das Gegenteil des positiven Trennzeichens; wenn der enthaltene Ausdruck nicht in der Zeichenfolge sein kann

Es hilft zu demonstrieren, wo die Weiterleitung erfolgreich sein kann. Stellen Sie sich ein einfaches Muster vor, das einen Dateinamen abgleicht und ihn in einen Basisnamen und ein „“ aufteilt. In „news.rc“ ist beispielsweise „news“ der Basisname und „rc“ ist die Dateierweiterung.


Das passende Muster ist sehr einfach:

Code-Hervorhebung erstellt von Actipro CodeHighlighter (Freeware)
http://www.CodeHighlighter.com/

-->. *[.][^b].*$

Der erste Versuch oben, „bat“ zu entfernen, erfordert, dass das erste Zeichen der Erweiterung etwas anderes als „b“ ist. Das ist falsch, da das Muster auch nicht mit „foo.bar“ übereinstimmen kann.

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

Der Ausdruck wird noch chaotischer, wenn Sie versuchen, die erste Lösung so zu patchen, dass eine der folgenden Bedingungen erfüllt ist: Das erste Zeichen der Erweiterung ist nicht „b“ oder das dritte Zeichen Zeichen ist nicht „t“. Dies würde „foo.bar“ akzeptieren, aber „autoexec.bat“ ablehnen, würde aber nur eine dreistellige Erweiterung erfordern und würde keine zweistellige Erweiterung wie „sendmail.cf“ akzeptieren. Wir werden das Muster noch einmal verkomplizieren, während wir daran arbeiten, es zu patchen.

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

Im dritten Versuch wurden sowohl der zweite als auch der dritte Buchstabe optional gemacht, um passende Erweiterungen zu ermöglichen, die kürzer als drei Zeichen sind, wie zum Beispiel „sendmail. cf“.


Das Muster ist mittlerweile sehr komplex, was die Lesbarkeit erschwert. Schlimmer noch: Wenn sich das Problem ändert und Sie andere Erweiterungen als „bat“ und „exe“ wünschen, wird das Muster noch komplizierter und verwirrender.


Vorwärtsnegierung schneidet all dies ab auf:

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

Vorwärtsbedeutung: Wenn der Ausdruck bat hier nicht übereinstimmt, versuchen Sie es mit dem Rest des Musters. Wenn bat$ übereinstimmt, schlägt das gesamte Muster fehl. Das abschließende $ ist erforderlich, um sicherzustellen, dass Erweiterungen, die mit „bat“ beginnen, wie „sample.batch“, zulässig sind.


Es ist jetzt einfach, eine andere Dateierweiterung auszuschließen; machen Sie sie einfach im Trennzeichen optional. Das folgende Muster schließt Dateinamen aus, die auf „bat“ oder „exe“ enden.

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

String ändern

Bisher haben wir einfach nach einem statischen String gesucht. Reguläre Ausdrücke werden normalerweise auch auf unterschiedliche Weise verwendet, um Zeichenfolgen über die unten stehende Methode „RegexObject“ zu ändern.

方法/属性 作用
split() 将字符串在 RE 匹配的地方分片并生成一个列表,
sub() 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换
subn() 与 sub() 相同,但返回新的字符串和替换次数

Teilen Sie die Zeichenfolge auf

Die Methode split() von „RegexObject“ teilt die Zeichenfolge dort, wo RE übereinstimmt, und gibt eine Liste zurück. Sie ähnelt der String-Split()-Methode, bietet jedoch mehr Trennzeichen. Split() unterstützt nur Leerzeichen und feste Zeichenfolgen. Wie zu erwarten ist, gibt es auch eine re.split()-Funktion auf Modulebene.

split(string [ , maxsplit = 0])

Teilen Sie die Zeichenfolge durch reguläre Ausdrücke. Werden in einem RE einfangende Klammern verwendet, wird deren Inhalt ebenfalls als Teil der Ergebnisliste zurückgegeben. Wenn maxsplit ungleich Null ist, können höchstens maxsplit-Shards geteilt werden.


Sie können die Anzahl der Teilungen begrenzen, indem Sie den Wert maxsplit festlegen. Wenn maxsplit ungleich Null ist, kann es höchstens maxsplit-Aufteilungen geben und der Rest der Zeichenfolge wird als letzter Teil der Liste zurückgegeben. In den folgenden Beispielen kann das Trennzeichen eine beliebige Folge nicht alphanumerischer Zeichen sein.

# !python

>>> p = re.compile(r'"W+')

> >> p.split('Dies ist ein kurzer und knapper Test von split().')

[
'Dies'' ist''ein''Test''kurz''und''süß ''von''aufgeteilt ''']

>>>  p.split('Dies ist ein Test, kurz und knapp, von split().'3)

[
'Dies' 'ist''ein''Test, kurz und bündig, von split().']

有时,你不仅对定界符之间的文本感兴趣,也需要知道定界符是什么.如果捕获括号在 RE用,那么它们的值也会当作列表的一部分返回.比较下面的调用:

# !python

>>> p = re.compile(r'"W+')

> >> p2 = re.compile(r'("W+)')

>>> p.split('Dies ist ein Test.')

[
'Dies ''ist''a ''Test''' ]

>>> p2.split('Dies ist ein Test.')

[
'Dies'' ''ist'' '' a'' ''test''.''']

模块级函数 re.split() 将 RE 作为第一个参数,其他一样。

# !python

>>> re.split('["W]+''Wörter, Wörter, Wörter.' )

[
'Wörter''Wörter''Wörter''']

>>> re.split('(["W]+)''Wörter, Wörter, Wörter. ')

[
'Wörter'' ''Wörter''''Wörter''.''']

>>> re.split('["W]+ ''Wörter, Wörter, Wörter.'1)

[
'Wörter'' Wörter, Wörter.']

搜索和替换

其他常见的用途就是找到所有模式匹配的字符串并用不同的字符串来替换它们.sub() 方法提供一个替换值, 可以是字符串或个函数,和一个要被处理的字符串.

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

Die zurückgegebene Zeichenfolge wird durch die nicht wiederkehrende Übereinstimmung von RE ganz links in der Zeichenfolge ersetzt. Wird das Muster nicht gefunden, wird das Zeichen unverändert zurückgegeben.


Der optionale Parameter count ist die maximale Anzahl von Ersetzungen nach dem Mustervergleich. count muss eine nicht negative ganze Zahl sein. Der Standardwert ist 0, der alle Übereinstimmungen ersetzt.


Hier ist ein einfaches Beispiel mit der sub()-Methode. Es ersetzt den Farbnamen durch das Wort „Farbe“.

# !python

>>> p = re.compile( '(blau|weiß|rot)')

>>> p.sub( 'Farbe', 'blaue Socken und rote Schuhe')

' Farbsocken und Farbschuhe'

>>> p.sub( 'Farbe', 'blaue Socken und rote Schuhe', zählen=1)

'Farbe Socken und rote Schuhe'

subn()-Methode hat den gleichen Effekt, gibt aber ein Zwei-Tupel zurück, das die neue Zeichenfolge und die Anzahl der Ersetzungsausführungszeiten enthält.

# !python

>>> p = re.compile( '(blau|weiß|rot)')

>>> p.subn( 'color', 'blaue Socken und rote Schuhe')

(
'farbige Socken und farbige Schuhe', 2)

>>> p.subn( 'Farbe', ' überhaupt keine Farben')

(
'überhaupt keine Farben', 0)

Leere Matches werden nur ersetzt, wenn sie nicht unmittelbar auf ein vorheriges Match folgen.

# !python

>>> p = re.compile('x*')

>> 'abxd')'-a-b-d- '

Wenn es sich bei der Ersetzung um eine Zeichenfolge handelt, werden alle darin enthaltenen Backslashes verarbeitet. „n“ wird in ein Zeilenumbruchzeichen umgewandelt, „r“ in einen Wagenrücklauf usw. Unbekannte Escapezeichen wie „j“ bleiben erhalten. Rückverweise wie „6“ werden mit der entsprechenden Gruppe im RE abgeglichen und durch die Teilzeichenfolge ersetzt. Dadurch können Sie einen Teil des Originaltextes in die ersetzte Zeichenfolge einfügen.
In diesem Beispiel wird das von „{“ und „}“ eingeschlossene Wort „Abschnitt“ abgeglichen und „Abschnitt“ durch „Unterabschnitt“ ersetzt.

# !python

>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)

>>> p.sub(r'subsection{"1} ','Abschnitt{Erster} Abschnitt{Zweiter}🎜>')

'subsection{First} subsection{second}'

kann auch mit (?P ..) Die Syntax definiert eine benannte Gruppe ", kann aber in der Ersetzungszeichenfolge eine unklare Bedeutung haben, z. B. "g<2>0". („20“ wird als Verweis auf Gruppe 20 interpretiert, nicht auf Gruppe 2, gefolgt von einem Buchstaben „0“.)

# !python

>>> p = re.compile('section{ (?P [^}]* ) }', re. VERBOSE)

>>> p.sub(r'subsection{"1}','Abschnitt{Erster🎜>')

'subsection{First}'

>>> p.sub(r'subsection{"g<1>}', 'Abschnitt{Erster🎜>')

'
Unterabschnitt{Erster🎜 >'
>>>
 p.sub(r' subsection{"g}','section{First}')
'
subsection{First}'
替换也可以是一个甚至给你更多控制的函数.如果替换是个函数,该函数将会被模式中每一个不重复的匹配所调用.在每个调用时, 函数被作为 `MatchObject ` 的匹配函属,并可以使用这个信息去计算预期的字符串并返回它.

在下面的例子里,替换函数将十进制翻译成十六进制:

# !python

>>> def hexrepl( match ):

     
"Gibt den Hex-String für eine Dezimalzahl zurück"

     value 
= int( match.group() )

     
return hex(Wert)



>>> p =  re.compile(r'"d+')

> ;>e; )'Rufen Sie 0xffd2 zum Ausdrucken und 0xc000 für den Benutzercode auf.'

常见问题正则表达式对一些应用程序来说是一个强大的工具,但在有些时候它并不直观而且有时它们不按你期望的运行.本节将指出一些最容易犯的常见错误.使用字符串方式有时使用 re 模块是个错误。如果你匹配一个固定的字符串或单个的字符类,并且你没有使用 re 的任何IGNORECASE wird nicht verwendet进行操作的, 它们通常快很多, 因为都是一个个经过优化的C 小循环, 用以代替大的、更具通用性的正则表达式引擎.

举个用一个固定字符串替换另一个的例子;如,你可以把 „Tat“ 替换成 „Wort“。re .sub() scheint die dafür zu verwendende Funktion zu sein, aber ziehen Sie die Methode replace() in Betracht. Sie können replace() verwenden, um „swordfish“ und „sdeedfish“ zu verwenden换单词的一部分,模式将写成 „bword“b,这是为了求 „Wort“从一个字符串中删除单个字符或用另一个字符来替代它.你也许可以用象 re.sub('"n',' ',S) 这样来实现, 但 Translate() 能够实现这两个任务, 而且比任何正则表达式操作起来更快.

总之,在使用 re 模块之前,先考虑一下你的问题是否可以用更快、更简单的字符串方法来解决。

match() vs. search()

Die Funktion match() prüft nur, ob RE am Anfang der Zeichenfolge übereinstimmt, während search() die gesamte Zeichenfolge durchsucht. Es ist wichtig, sich an diese Unterscheidung zu erinnern. Denken Sie daran, dass match() nur einen erfolgreichen Match meldet, der bei 0 beginnt; wenn der Match nicht bei 0 beginnt, wird match() ihn nicht melden.

# !python

>>> drucken re.match('super', 'Aberglaube ').span()

(0,
5)

>>> print re.match('super', 'unüberwindbar')

Keine

search() hingegen durchsucht die gesamte Zeichenfolge und meldet die erste gefundene Übereinstimmung.

# !python

>>> drucken re.search('super', 'Aberglaube ').span()

(0,
5)

>>> drucken re.search('super', 'unüberwindbar').span()

(
2, 7)

Manchmal neigen Sie möglicherweise dazu, nur re.match() zu verwenden if Fügen Sie .* zum vorderen Teil von RE hinzu. Versuchen Sie bitte, dies nicht zu tun und verwenden Sie stattdessen re.search(). Der Compiler für reguläre Ausdrücke führt eine Analyse der REs durch, um die Verarbeitung bei der Suche nach Übereinstimmungen zu beschleunigen. Ein solcher Parser gibt an, welches das erste Zeichen der Übereinstimmung ist; zum Beispiel muss das Muster „Crow“ beginnend mit „C“ übereinstimmen. Der Parser ermöglicht es der Engine, die Zeichenfolge schnell zu scannen, um das Startzeichen zu finden, und erst dann mit dem Abgleich aller Zeichen zu beginnen, wenn „C“ gefunden wurde.

Das Hinzufügen von .* führt dazu, dass diese Optimierung fehlschlägt, was ein Scannen bis zum Ende der Zeichenfolge und dann ein Zurückverfolgen erfordert, um eine Übereinstimmung für den Rest der RE zu finden. Verwenden Sie stattdessen re.search().

Gierig vs. nicht gierig

Wenn ein regulärer Ausdruck wiederholt wird, beispielsweise mit a*, besteht das Ergebnis der Operation darin, so viele Muster wie möglich abzugleichen. Diese Tatsache stört Sie oft, wenn Sie versuchen, ein symmetrisches Trennzeichenpaar, wie z. B. spitze Klammern, im HTML-Markup zuzuordnen. Muster, die mit einem einzelnen HTML-Tag übereinstimmen, funktionieren aufgrund der „gierigen“ Natur von .* nicht richtig. CodeHighlighter.com/

-->#!python

pat
= re .compile(r"""

"s*                            # Führendes Leerzeichen überspringen

(?P

[^: ]+) # Headername

"S*:>
# Verlieren Sie die folgende nachfolgende Whitespace

"
"""

, re.VERBOSE)

Dieser ist viel schwerer zu lesen: Code-Hervorhebung erzeugt von Actipro CodeHighlighter (Freeware)

http://www .CodeHighlighter.com/

-->

#

Das obige ist der detaillierte Inhalt vonEine detailliertere Anleitung zu Python-Operationen mit regulären Ausdrücken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn