Qual è la differenza tra re.search e re.match?
Domanda
Qual è la differenza tra le funzioni search ()
e match ()
nelle modulo Python re
?
Ho letto la documentazione (< a href = "http://docs.python.org/2/library/re.html?highlight=matching%20searching#search-vs-match" rel = "noreferrer"> documentazione corrente ), ma I sembra non ricordarlo mai. Continuo a cercare e riapprenderlo. Spero che qualcuno risponderà chiaramente con esempi in modo che (forse) mi si attacchi alla testa. O almeno avrò un posto migliore per tornare con la mia domanda e ci vorrà meno tempo per riapprenderla.
Soluzione
re.match
è ancorato all'inizio della stringa. Non ha nulla a che fare con le nuove righe, quindi non è lo stesso che usare ^
nel modello.
Come dice la re.match documentazione :
Se zero o più caratteri in inizio della stringa corrisponde al modello di espressione regolare, restituisce a istanza
MatchObject
corrispondente. RestituisceNessuno
se la stringa no abbinare il modello; si noti che questo è diverso da una corrispondenza di lunghezza zero.Nota: se si desidera individuare una corrispondenza dovunque nella stringa, usa
search ()
invece.
re.search
cerca nell'intera stringa, come la documentazione dice :
Scansiona la stringa cercando un posizione in cui l'espressione regolare il modello produce una corrispondenza e restituisce a istanza
MatchObject
corrispondente. RestituisceNessuno
se nessuna posizione in la stringa corrisponde al modello; nota che questo è diverso dal trovare un corrispondenza di lunghezza zero ad un certo punto nel stringa.
Quindi, se devi abbinare all'inizio della stringa o per far corrispondere l'intera stringa usa match
. È più veloce. Altrimenti usa cerca
.
La documentazione ha una sezione specifica per match
vs. cerca
che copre anche stringhe multilinea:
Python offre due primitive diverse operazioni basate su regolari espressioni:
match
verifica una corrispondenza solo all'inizio della stringa, mentrecerca
verifica una corrispondenza ovunque nella stringa (ecco cosa Perl lo fa di default).Nota che
corrisponde
può differire dacerca
anche quando si utilizza un'espressione regolare che inizia con'^'
:'^'
corrisponde solo a all'inizio della stringa o dentro Anche la modalitàMULTILINE
immediatamente seguendo una nuova riga. La "match
" l'operazione ha esito solo se il modello corrispondenze all'inizio della stringa indipendentemente dalla modalità o all'inizio posizione data dalpos
opzionale argomento indipendentemente dal fatto che a newline lo precede.
Ora, basta parlare. È ora di vedere qualche codice di esempio:
# 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
Altri suggerimenti
cerca
? trova qualcosa in qualsiasi punto della stringa e restituisce un oggetto match.
match
? trova qualcosa inizio della stringa e restituisce un oggetto match.
re.search
cerca es per il pattern in tutta la stringa , mentre re.match
fa non cercare il modello; in caso contrario, non ha altra scelta che abbinarlo all'inizio della stringa.
è possibile fare riferimento all'esempio seguente per comprendere il funzionamento di re.match e re.search
a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)
re.match non restituirà nessuno, ma re.search restituirà abc.
La differenza è che re.match ()
induce in errore chiunque sia abituato a Perl , grep o sed corrispondenza delle espressioni regolari e re.search ()
no. :-)
Più seriamente, Come osserva John D. Cook , re.match ( )
" si comporta come se ogni modello abbia ^ anteposto. " In altre parole, re.match ('pattern')
è uguale a re.search ('^ pattern')
. Quindi fissa il lato sinistro di un motivo. Ma anche non fissa il lato destro di un pattern: che richiede ancora un $
terminante.
Detto francamente quanto sopra, penso che re.match ()
dovrebbe essere deprecato. Sarei interessato a sapere i motivi per cui dovrebbe essere mantenuto.
La corrispondenzaè molto più veloce della ricerca, quindi invece di eseguire regex.search (" word ") puoi eseguire regex.match ((. *?) word (. *?)) e ottenere tonnellate di prestazioni se lo sei lavorando con milioni di campioni.
Questo commento di @ivan_bilan sotto il risposta accettata sopra mi ha fatto pensare se tale hack stia effettivamente accelerando qualcosa, quindi scopriamo quante tonnellate di prestazioni otterrai davvero.
Ho preparato la seguente suite di test:
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)
Ho effettuato 10 misurazioni (1 M, 2 M, ..., 10 M parole) che mi hanno dato il seguente diagramma:
Le linee risultanti sono sorprendentemente (in realtà non così sorprendentemente) dritte. E la funzione cerca
è (leggermente) più veloce data questa combinazione di pattern specifica. La morale di questo test: Evita di ottimizzare il tuo codice.
re.match tenta di far corrispondere un modello all'inizio della stringa . re.search tenta di abbinare il modello in tutta la stringa fino a quando non trova una corrispondenza.
Molto più breve:
cerca
scansiona l'intera stringa.corrisponde
Fa solo l'inizio della stringa.
Il seguente Ex lo dice:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc