Was ist der Unterschied zwischen re.search und re.match?
Frage
Was ist der Unterschied zwischen den search()
und match()
Funktionen in dem Python re
Modul ?
Ich habe die Dokumentation lesen (< a href = "http://docs.python.org/2/library/re.html?highlight=matching%20searching#search-vs-match" rel = "noreferrer"> aktuelle Dokumentation ), aber ich nie scheint es zu merken. Ich muss immer wieder danach suchen und wieder lernen es. Ich hoffe, dass jemand es eindeutig mit Beispielen zu beantworten, so dass (vielleicht) es in meinem Kopf bleiben wird. Oder zumindest werde ich zu einem besseren Ort mit meiner Frage zurückkommen müssen, und es wird weniger Zeit in Anspruch nehmen, um es neu zu lernen.
Lösung
re.match
wird am Anfang des Strings verankert. Das hat nichts mit Zeilenumbrüchen zu tun, so ist es nicht die gleiche wie mit ^
im Muster.
Als re.match Dokumentation sagt:
Wenn null oder mehr Zeichen bei der Anfang Zeichenfolge , um das Muster eines regulären Ausdrucks übereinstimmen, kehren ein entsprechende
MatchObject
Instanz. RückNone
, wenn die Zeichenfolge nicht der Fall ist entspricht das Muster; beachten Sie, dass dies unterscheidet sich von einer Null-Länge übereinstimmen.Hinweis: Wenn Sie möchten, um eine Übereinstimmung finden überall in string, verwenden
search()
statt.
re.search
sucht die gesamte Zeichenfolge, wie die Dokumentation sagt :
Scan durch Zeichenfolge Suche nach einem Ort, an dem der regulären Ausdruck Muster erzeugt ein Spiel, und das Rück ein entsprechende
MatchObject
Instanz. ZurückNone
, wenn keine Position in der String mit dem Muster; beachten Sie, dass Dies unterscheidet sich von der Suche nach einem an einem gewissen Punkt der Länge Null Spiel in der String.
Wenn Sie also am Anfang der Zeichenfolge übereinstimmen, oder die gesamte Zeichenfolge Verwendung match
anzupassen. Es ist schneller. Ansonsten search
verwenden.
Die Dokumentation hat einen für match
vs. search
, die umfasst auch mehrzeilige Strings:
Python bietet zwei verschiedene primitive Operationen auf der Grundlage regelmäßiger Ausdrücke:
match
prüft, ob ein Spiel nur am Anfang der Zeichenfolge, währendsearch
prüft, ob ein Spiel irgendwo in der Zeichenkette (das ist, was Perl tut Standard).Beachten Sie, dass
match
vonsearch
abweichen selbst wenn ein regulären Ausdruck mit'^'
beginnen:'^'
passt nur zu Beginn des Strings, oder inMULTILINE
Modus sofort auch nach einem Newline. Die „match
“ Operation erfolgreich nur, wenn das Muster Spiele in der Start der Zeichenfolge unabhängig vom Modus oder am Start Position durch den optionalenpos
gegeben Argument unabhängig davon, ob ein Newline vorangeht.
Nun, genug geredet. Zeit, um einige Beispiel-Code, um zu sehen:
# 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
Andere Tipps
search
⇒ etwas irgendwo im String finden und ein Match-Objekt zurück.
match
⇒ etwas finden, an dem Anfang der Zeichenfolge und gibt ein Match-Objekt.
re.search
Suche es für das Muster in der gesamten Zeichenfolge , während re.match
tut nicht suchen das Muster; wenn dies nicht der Fall, es hat keine andere Wahl, als zu Spiel es am Anfang des Strings.
Sie können das unten stehende Beispiel beziehen sich die Arbeits von re.match und re.search verstehen
a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)
re.match kehrt keine, aber re.search wird abc zurück.
Der Unterschied ist, verleitet re.match()
jemand daran gewöhnt, Perl grep oder sed reguläre Ausdrücke und re.search()
nicht . : -)
nüchterner, Wie John D. Koch bemerkt , re.match()
„verhält, als ob jedes Muster hat ^ vorangestellt.“ Mit anderen Worten entspricht re.match('pattern')
re.search('^pattern')
. So verankert sie eine linke Seite des Musters. Aber es auch nicht ein rechte Seite des Musters verankern. , die noch ein abschließendes $
erfordert
Ehrlich gesagt die oben angegebenen, denke ich re.match()
veraltet werden sollte. Es würde mich interessieren Gründe zu wissen, es sollte beibehalten werden.
Spiel ist viel schneller als Suche, so dass anstelle regex.search zu tun ( „Wort“), können Sie Regex.Match tun ((. *?) Wort (. *?)) Und jede Menge Leistung gewinnen, wenn Sie arbeiten mit Millionen von Proben.
Dieser Kommentar von @ivan_bilan unter der akzeptierte Antwort oben hat mir denken, wenn eine solche Hack ist eigentlich alles bis zu beschleunigen, also lassen Sie uns herausfinden, wie viele Tonnen Leistung, die Sie wirklich gewinnen.
ich bereit, die folgende Testsuite:
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 (1M, 2M, ..., 10M Worte), die mir die folgende Handlung gab:
Die resultierenden Linien sind überraschend (eigentlich gar nicht so überraschend) gerade. Und die search
Funktion ist (leicht) schneller angesichts dieser spezifische Musterkombination. Die Moral dieser Test: Vermeiden Sie den Code overoptimizing
re.match ein Muster zu entsprechen versucht am Anfang der Zeichenfolge . re.search versucht, das Muster in der gesamten Zeichenfolge passen, bis eine Übereinstimmung gefunden wird.
Viel kürzer:
-
search
Scans Trog ganze Reihe. -
match
Hat erst am Anfang der Zeichenfolge.
Im Anschluss an Ex heißt es:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc