Qual è la differenza tra re.search e re.match?


527

Qual è la differenza tra le funzioni search()e match()nel modulo Pythonre ?

Ho letto la documentazione ( documentazione attuale ), ma non mi sembra di ricordarmelo 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.

Risposte:


508

re.matchè ancorato all'inizio della stringa. Non ha nulla a che fare con le nuove linee, quindi non è lo stesso che usare ^nel modello.

Come dice la documentazione di re.match :

Se zero o più caratteri all'inizio della stringa corrispondono al modello di espressione regolare, restituisce MatchObjectun'istanza corrispondente . Restituisce Nonese la stringa non corrisponde al modello; si noti che questo è diverso da una corrispondenza di lunghezza zero.

Nota: se si desidera individuare una corrispondenza in qualsiasi punto della stringa, utilizzare search() invece.

re.searchcerca l'intera stringa, come dice la documentazione :

Scansione attraverso la stringa alla ricerca di una posizione in cui il modello di espressione regolare produce una corrispondenza e restituisce MatchObjectun'istanza corrispondente . Restituisce Nonese nessuna posizione nella stringa corrisponde al modello; nota che questo è diverso dal trovare una corrispondenza di lunghezza zero in qualche punto della stringa.

Quindi, se hai bisogno di abbinare all'inizio della stringa, o per abbinare l'intera stringa usa match. È più veloce. Altrimenti usa search.

La documentazione ha una sezione specifica per matchvs.search che copre anche le stringhe multilinea:

Python offre due diverse operazioni primitive basate su espressioni regolari: matchcontrolla una corrispondenza solo all'inizio della stringa, mentre searchcontrolla una corrispondenza in qualsiasi punto della stringa (questo è ciò che Perl fa di default).

Si noti che matchpuò differire search anche quando si utilizza un'espressione regolare che inizia con '^': '^'corrisponde solo all'inizio della stringa o in MULTILINEmodalità anche immediatamente dopo una nuova riga. L' matchoperazione " " ha esito positivo solo se il modello corrisponde all'inizio della stringa indipendentemente dalla modalità o nella posizione iniziale indicata pos dall'argomento facoltativo indipendentemente dal fatto che una nuova riga la precede.

Adesso 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

Che dire delle stringhe contenenti newline?
Daryl Spitzer,

26
Perché qualcuno dovrebbe usare limitato matchpiuttosto che più generale searchallora? è per la velocità?
Alby,

13
La corrispondenza @Alby è molto più veloce della ricerca, quindi invece di fare regex.search ("parola") puoi fare regex.match ((. *?) Parola (. *?)) E ottenere tonnellate di prestazioni se lavori con milioni di campioni.
ivan_bilan,

20
Bene, è sciocco. Perché chiamarlo match? È una manovra intelligente seminare le API con nomi non intuitivi per costringermi a leggere la documentazione? Non lo farò ancora! Ribelle!
Sammaron,

1
@ivan_bilan matchsembra un po ' fasterpiù di ricerca quando si usa la stessa espressione regolare, ma il tuo esempio sembra sbagliato in base a un test di prestazione: stackoverflow.com/questions/180986/...
baptx

101

search ⇒ trova qualcosa in qualsiasi punto della stringa e restituisce un oggetto corrispondente.

match⇒ trova qualcosa all'inizio della stringa e restituisce un oggetto match.


49

re.search cercare es per il modello in tutta la stringa , mentre re.matchnon non cercare il modello; in caso contrario, non ha altra scelta che abbinarlo all'inizio della stringa.


5
Perché abbinare all'inizio, ma non fino alla fine della stringa ( fullmatchin phyton 3.4)?
Smit Johnth,

49

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 lavori con milioni di campioni.

Questo commento di @ivan_bilan sotto la risposta accettata sopra mi ha fatto pensare se tale hack sta 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 fatto 10 misurazioni (1 M, 2 M, ..., 10 M parole) che mi ha dato il seguente diagramma:

match vs search regex trama della linea speedtest

Le linee risultanti sono sorprendentemente (in realtà non così sorprendentemente) dritte. E la searchfunzione è (leggermente) più veloce data questa combinazione di pattern specifica. La morale di questo test: evita di ottimizzare il tuo codice.


12
+1 per aver effettivamente indagato sulle ipotesi alla base di un'affermazione che doveva essere presa al valore nominale - grazie.
Robert Dodier,

In effetti il ​​commento di @ivan_bilan sembra sbagliato ma la matchfunzione è ancora più veloce della searchfunzione se si confronta la stessa espressione regolare. Puoi controllare il tuo script confrontandolo re.search('^python', word)con re.match('python', word)(o re.match('^python', word)quale è lo stesso ma più facile da capire se non leggi la documentazione e sembra non influire sulle prestazioni)
baptx

@baptx Non sono d'accordo con l'affermazione che la matchfunzione è generalmente più veloce. Ilmatch è più veloce quando si desidera effettuare la ricerca , all'inizio della stringa, il searchè più veloce quando si desidera effettuare la ricerca in tutta la stringa. Che corrisponde al buon senso. Ecco perché @ivan_bilan aveva torto: era solito matchcercare in tutta la stringa. Ecco perché hai ragione: matchcercavi all'inizio della stringa. Se non sei d'accordo con me, prova a trovare regex perché matchè più veloce di re.search('python', word)e fa lo stesso lavoro.
Jeyekomon il

@baptx Inoltre, come nota a piè di pagina, re.match('python') è leggermente più veloce di re.match('^python'). Deve essere.
Jeyekomon il

@Jeyekomon sì, è quello che volevo dire, match funzione è un po 'più veloce se vuoi cercare all'inizio di una stringa (rispetto all'utilizzo della searchfunzione per trovare una parola all'inizio di una stringa, re.search('^python', word)ad esempio). Ma lo trovo strano, se dici alla searchfunzione di cercare all'inizio di una stringa, dovrebbe essere veloce come la matchfunzione.
battezzare il

31

È possibile fare riferimento all'esempio seguente per comprendere il funzionamento re.matche la ricerca di re

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

re.matchtornerà none, ma re.searchtornerà abc.


3
Vorrei solo aggiungere che la ricerca restituirà l'oggetto _sre.SRE_Match (o None se non trovato). Per ottenere 'abc', è necessario chiamare t.group ()
Sand

30

La differenza è che re.match()fuorvia chiunque sia abituato a Perl , grep corrispondenza di espressioni regolari o sed , e re.search()non lo fa. :-)

Più seriamente, come osserva John D. Cook , re.match()"si comporta come se ogni modello abbia ^ anteposto". In altre parole,re.match('pattern') uguale re.search('^pattern'). Quindi fissa il lato sinistro di un motivo. Ma non fissa anche il lato destro di un modello: ciò richiede ancora una terminazione $.

Francamente dato quanto sopra, penso che re.match()dovrebbe essere deprecato. Sarei interessato a sapere i motivi per cui dovrebbe essere mantenuto.


4
"si comporta come se ogni modello abbia ^ anteposto." è vero solo se non si utilizza l'opzione multilinea. L'affermazione corretta è "... ha \ A anteposto"
JoelFan,

14

re.match tenta di far corrispondere un modello all'inizio della stringa . re.search tenta di far corrispondere il modello in tutta la stringa fino a quando non trova una corrispondenza.


3

Molto più breve:

  • search esegue la scansione dell'intera stringa.

  • match analizza solo l'inizio della stringa.

A seguire Ex lo dice:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.