681 Stimmen

Was ist der Unterschied zwischen re.search und re.match?

Was ist der Unterschied zwischen dem search() y match() Funktionen im Python re Modul ?

Ich habe die Dokumentation ( aktuelle Dokumentation ), aber ich scheine mich nie daran zu erinnern. Ich muss es immer wieder nachschlagen und neu lernen. Ich hoffe, dass mir jemand eine klare Antwort mit Beispielen gibt, damit ich sie (vielleicht) im Gedächtnis behalte. Oder zumindest habe ich dann eine bessere Anlaufstelle für meine Frage und brauche weniger Zeit, um sie neu zu lernen.

656voto

nosklo Punkte 204121

re.match wird am Anfang der Zeichenkette verankert. Das hat nichts mit Zeilenumbrüchen zu tun, ist also nicht dasselbe wie die Verwendung von ^ in dem Muster.

Da die re.match Dokumentation sagt:

Wenn null oder mehr Zeichen an der Anfang der Zeichenkette mit dem Muster des regulären Ausdrucks übereinstimmen, geben eine entsprechende MatchObject Instanz. Rückgabe None wenn die Zeichenkette nicht dem Muster entspricht; beachten Sie, dass dies eine sich von einer Null-Längen-Übereinstimmung unterscheidet.

Hinweis: Wenn Sie eine Übereinstimmung suchen wollen irgendwo in der Zeichenkette suchen wollen, verwenden Sie search() stattdessen.

re.search durchsucht die gesamte Zeichenkette, während In der Dokumentation heißt es :

String durchsuchen auf der Suche nach einem Stelle, an der der reguläre Ausdruck Muster eine Übereinstimmung ergibt, und gibt eine entsprechende MatchObject Instanz. Rückgabe None wenn keine Position im Zeichenfolge mit dem Muster übereinstimmt; beachten Sie, dass dies etwas anderes ist als das Finden einer Null-Längen-Übereinstimmung an einer Stelle in der Zeichenfolge.

Wenn Sie also eine Übereinstimmung am Anfang der Zeichenkette benötigen oder die gesamte Zeichenkette abgleichen möchten, verwenden Sie match . Das ist schneller. Ansonsten verwenden search .

Die Dokumentation enthält eine spezifischer Abschnitt für match vs. search die auch mehrzeilige Zeichenfolgen abdeckt:

Python bietet zwei verschiedene primitive Operationen, die auf regulären Ausdrücken: match sucht nach einer Übereinstimmung nur am Anfang der Zeichenkette, während search sucht nach einer Übereinstimmung überall in der Zeichenkette (das ist das, was Perl standardmäßig macht).

Beachten Sie, dass match kann abweichen von search auch bei Verwendung eines regulären Ausdrucks der mit '^' : '^' passt nur am Anfang der Zeichenkette, oder in MULTILINE Modus auch sofort nach einem Zeilenumbruch. Die " match " Operation gelingt nur, wenn das Muster mit der Start der Zeichenkette unabhängig vom Modus, oder beim Start Position, die durch den optionalen Parameter pos Argument unabhängig davon, ob ein Zeilenumbruch vorausgeht.

So, genug geredet. Es ist Zeit für ein paar Beispielcodes:

# example code:
string_with_newlines = """something
someotherthing"""

import re

print re.match('some', string_with_newlines) # matches
print re.match('someother', 
               string_with_newlines) # won't match
print re.match('^someother', string_with_newlines, 
               re.MULTILINE) # also won't match
print re.search('someother', 
                string_with_newlines) # finds something
print re.search('^someother', string_with_newlines, 
                re.MULTILINE) # also finds something

m = re.compile('thing$', re.MULTILINE)

print m.match(string_with_newlines) # no match
print m.match(string_with_newlines, pos=4) # matches
print m.search(string_with_newlines, 
               re.MULTILINE) # also matches

0 Stimmen

Was ist mit Zeichenketten, die Zeilenumbrüche enthalten?

0 Stimmen

Auch bei Zeichenketten, die Zeilenumbrüche enthalten, passt match() nur am ANFANG der Zeichenkette.

0 Stimmen

Das ist die Antwort, auf die ich gehofft hatte! (Vor allem jetzt, da Sie ein Beispiel gegeben haben.)

141voto

search ⇒ irgendwo in der Zeichenkette etwas finden und ein Match-Objekt zurückgeben.

match ⇒ finden Sie etwas im Anfang der Zeichenkette und geben ein Match-Objekt zurück.

104voto

Jeyekomon Punkte 2288

match ist viel schneller als search. Anstelle von regex.search("word") können Sie also regex.match((.*?)word(.*?)) verwenden und so eine Menge Leistung gewinnen, wenn Sie mit Millionen von Beispielen arbeiten.

Dieser Kommentar von @ivan_bilan unter der akzeptierten Antwort oben hat mich zum Nachdenken gebracht, ob solche hacken. tatsächlich etwas beschleunigt, also lassen Sie uns herausfinden, wie viele Tonnen Leistung Sie wirklich gewinnen werden.

Ich habe die folgende Testsuite vorbereitet:

import random
import re
import string
import time

LENGTH = 10
LIST_SIZE = 1000000

def generate_word():
    word = [random.choice(string.ascii_lowercase) for _ in range(LENGTH)]
    word = ''.join(word)
    return word

wordlist = [generate_word() for _ in range(LIST_SIZE)]

start = time.time()
[re.search('python', word) for word in wordlist]
print('search:', time.time() - start)

start = time.time()
[re.match('(.*?)python(.*?)', word) for word in wordlist]
print('match:', time.time() - start)

Ich habe 10 Messungen durchgeführt (1M, 2M, ..., 10M Wörter), die mir die folgende Darstellung lieferten:

match vs. search regex speedtest line plot

Wie Sie sehen können, Suche nach dem Muster 'python' ist schneller als die Übereinstimmung mit dem Muster '(.*?)python(.*?)' .

Python ist schlau. Vermeiden Sie den Versuch, schlauer zu sein.

40 Stimmen

+1 dafür, dass Sie die Annahmen hinter einer Aussage, die für bare Münze genommen werden soll, tatsächlich untersucht haben - danke.

2 Stimmen

Der Kommentar von @ivan_bilan sieht zwar falsch aus, aber die match Funktion ist immer noch schneller als die search Funktion, wenn Sie denselben regulären Ausdruck vergleichen. Sie können dies in Ihrem Skript überprüfen, indem Sie vergleichen re.search('^python', word) a re.match('python', word) (oder re.match('^python', word) was dasselbe ist, aber einfacher zu verstehen, wenn man die Dokumentation nicht liest, und die Leistung nicht zu beeinträchtigen scheint)

3 Stimmen

@baptx Ich stimme nicht mit der Aussage überein, dass die match Funktion ist im Allgemeinen schneller. Die Website match ist schneller, wenn Sie suchen wollen zu Beginn der Zeichenkette, die search ist schneller, wenn Sie suchen wollen auf die Zeichenfolge. Das entspricht dem gesunden Menschenverstand. Deshalb lag @ivan_bilan falsch - er verwendete match um die gesamte Zeichenkette zu durchsuchen. Deshalb haben Sie recht - Sie haben match um am Anfang der Zeichenkette zu suchen. Wenn Sie mit mir nicht einverstanden sind, versuchen Sie, eine Regex für match die schneller ist als re.search('python', word) und erfüllt die gleiche Aufgabe.

59voto

xilun Punkte 621

re.search Suche es für das Muster in der gesamten Kette in der Erwägung, dass re.match fait nicht suchen das Muster; ist dies nicht der Fall, hat es keine andere Wahl als Spiel es am Anfang der Zeichenkette.

5 Stimmen

Warum Übereinstimmung am Anfang, aber nicht bis zum Ende der Zeichenkette ( fullmatch in phyton 3.4)?

41voto

ldR Punkte 391

Anhand des folgenden Beispiels können Sie die Funktionsweise von re.match und re.search

a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)

re.match wird zurückgegeben none pero re.search wird zurückgegeben abc .

5 Stimmen

Ich möchte nur hinzufügen, dass die Suche das Objekt _sre.SRE_Match (oder None, wenn nicht gefunden) zurückgibt. Um 'abc' zu erhalten, müssen Sie t.group() aufrufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X