web-dev-qa-db-fra.com

Quelle est la différence entre re.search et re.match?

Quelle est la différence entre les fonctions search() et match() du module Python re ?

J'ai lu le documentation ( documentation actuelle ), mais je ne semble jamais m'en souvenir. Je continue à avoir à le chercher et à le réapprendre. J'espère que quelqu'un y répondra clairement par des exemples afin que (peut-être) cela me reste dans la tête. Ou du moins, ma question me permettra de revenir plus facilement et il faudra moins de temps pour la réapprendre.

451
Daryl Spitzer

re.match est ancré au début de la chaîne. Cela n’a rien à voir avec les nouvelles lignes, ce n’est donc pas la même chose que d’utiliser ^ dans le motif.

Comme le documentation re.match dit:

Si zéro ou plusieurs caractères au début de la chaîne correspondent au modèle d'expression régulière, renvoyez une instance MatchObject correspondante. Renvoie None si la chaîne ne correspond pas au modèle; notez que cela diffère d'une correspondance de longueur nulle.

Remarque: Si vous souhaitez localiser une correspondance n'importe où dans la chaîne, utilisez plutôt search().

re.search recherche dans toute la chaîne, comme la documentation le dit :

Parcourez la chaîne à la recherche d'un emplacement où le modèle d'expression régulière produit une correspondance et renvoyez une instance MatchObject correspondante. Renvoie None si aucune position dans la chaîne ne correspond au motif; Notez que cela diffère de la recherche d'une correspondance de longueur nulle à un moment donné de la chaîne.

Donc, si vous avez besoin de faire correspondre au début de la chaîne, ou pour faire correspondre toute la chaîne, utilisez match. C'est plus rapide. Sinon, utilisez search.

La documentation a une section spécifique pour match vs. search qui couvre également les chaînes multilignes:

Python propose deux opérations primitives différentes basées sur des expressions régulières: match recherche une correspondance uniquement au début de la chaîne, tandis que search vérifie la présence d'une correspondance n'importe où dans la chaîne (c'est ce que Perl fait par défaut).

Notez que match peut différer de search même si vous utilisez une expression régulière commençant par '^': '^' ne correspond qu'au début de la chaîne ou à MULTILINE. mode également immédiatement après une nouvelle ligne. L’opération “match” réussit uniquement si le modèle correspond au début de la chaîne quel que soit le mode ou à la position de départ indiquée par l’argument optionnel pos, qu’il soit précédé ou non d’une nouvelle ligne.

Maintenant, assez parlé. Il est temps de voir un exemple de code:

# 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
454
nosklo

search ⇒ trouver quelque chose n'importe où dans la chaîne et retourner un objet match.

match ⇒ trouvez quelque chose au début de la chaîne = et retournez un objet correspondant.

86

re.searchrecherche es pour le motif dans toute la chaîne, alors que re.match ne fait pas de recherche le motif; si ce n'est pas le cas, il n'a pas d'autre choix que de faire correspondre au début de la chaîne.

46
xilun

la correspondance est beaucoup plus rapide que la recherche. Ainsi, au lieu de faire regex.search ("Word"), vous pouvez le faire avec regex.match ((. *?) Word (. *?)) et gagner des tonnes de performances si vous travaillez avec des millions de fichiers. des échantillons.

Ce commentaire de @ivan_bilan sous la réponse acceptée ci-dessus m'a fait penser si un tel hack accélère réellement quoi que ce soit, alors voyons combien de tonnes de performances vous allez vraiment gagner.

J'ai préparé la suite de tests suivante:

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)

J'ai fait 10 mesures (1M, 2M, ..., 10M mots) qui m'ont donné l'intrigue suivante:

match vs. search regex speedtest line plot

Les lignes résultantes sont étonnamment droites (en fait pas étonnamment). Et la fonction search est (légèrement) plus rapide étant donné cette combinaison de motif spécifique. La morale de ce test: Évitez d’optimiser votre code.

30
Jeyekomon

La différence est la suivante: re.match() trompe quiconque est habitué à Perl , grep , ou sed la correspondance d'expression régulière, et re.search() ne le fait pas. :-)

Plus sobrement, Comme le fait remarquer John D. Cook , re.match() "se comporte comme si chaque motif avait été préposé". En d'autres termes, re.match('pattern') est égal à re.search('^pattern'). Donc, il ancre le côté gauche d'un motif. Mais cela n'empêche pas non plus le côté droit d'un motif: qui nécessite toujours une terminaison $.

Franchement, étant donné ce qui précède, je pense que re.match() devrait être obsolète. Je serais intéressé de connaître les raisons pour lesquelles il devrait être conservé.

25
CODE-REaD

Vous pouvez vous référer à l'exemple ci-dessous pour comprendre le fonctionnement de re.match et re.search

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

re.match retournera none, mais re.search retournera abc.

25
ldR

re.match tente de faire correspondre un modèle au début de la chaîne. re.search tente de faire correspondre le modèle tout au long de la chaîne jusqu'à ce qu'il trouve une correspondance.

14
cschol

Plus court:

  • search balaye l'intégralité de la chaîne.

  • match Fait seulement le début de la chaîne.

Après Ex le dit:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
1
U10-Forward