¿Cuál es la diferencia entre re.search y re.match?

¿Cuál es la diferencia entre las funciones search() y match() en el módulo de Python re ?

He leído la documentación ( documentación actual ), pero parece que nunca la recuerdo. Sigo teniendo que buscarlo y volver a aprenderlo. Espero que alguien lo responda claramente con ejemplos para que (quizás) se quede en mi cabeza. O al menos tendré un mejor lugar para volver con mi pregunta y me llevará menos tiempo volver a aprenderla.

re.match está anclado al principio de la cadena. Eso no tiene nada que ver con las nuevas líneas, por lo que no es lo mismo que usar ^ en el patrón.

Como dice la documentación de re.match :

Si cero o más caracteres al principio de la cadena coinciden con el patrón de expresión regular, devuelva una instancia de MatchObject correspondiente. Devuelva None si la cadena no coincide con el patrón; tenga en cuenta que esto es diferente de una coincidencia de longitud cero.

Nota: Si desea ubicar una coincidencia en cualquier lugar de la cadena, use search() lugar.

re.search busca en toda la cadena, como dice la documentación :

Escanee a través de la cadena en busca de una ubicación donde el patrón de expresión regular produzca una coincidencia y devuelva una instancia de MatchObject correspondiente. Devuelva None si ninguna posición en la cadena coincide con el patrón; tenga en cuenta que esto es diferente de encontrar una coincidencia de longitud cero en algún punto de la cadena.

Entonces, si necesita hacer coincidir al principio de la cadena, o para hacer coincidir toda la cadena, use la match . Es mas rapido. De lo contrario, utilice la search .

La documentación tiene una sección específica para la comparación de search que también cubre cadenas multilínea:

Python ofrece dos operaciones primitivas diferentes basadas en expresiones regulares: la match busca una coincidencia solo al comienzo de la cadena, mientras que la search busca una coincidencia en cualquier parte de la cadena (esto es lo que Perl hace de forma predeterminada).

Tenga en cuenta que la match puede diferir de la search incluso cuando se usa una expresión regular que comienza con '^' : '^' coincide solo con el inicio de la cadena, o en el modo MULTILINE también inmediatamente después de una nueva línea. La operación de ” match ” tiene éxito solo si el patrón coincide al comienzo de la cadena independientemente del modo, o en la posición inicial dada por el argumento pos opcional independientemente de si una nueva línea la precede.

Ahora, basta de hablar. Es hora de ver algún código de ejemplo:

 # 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 

search ⇒ encontrar algo en cualquier parte de la cadena y devolver un objeto coincidente.

match ⇒ encuentre algo al principio de la cadena y devuelva un objeto coincidente.

re.search busca el patrón en toda la cadena , mientras que re.match no busca el patrón; si no lo hace, no tiene otra opción que coincidir con el inicio de la cadena.

La diferencia es que re.match() confunde a cualquiera que esté acostumbrado a la concordancia de expresiones regulares Perl , grep o sed , y re.search() no. 🙂

De manera más sobria, como lo señala John D. Cook , re.match() “se comporta como si todos los patrones se re.match() “. En otras palabras, re.match('pattern') es igual a re.search('^pattern') . Así ancla el lado izquierdo de un patrón. Pero tampoco ancla el lado derecho de un patrón: eso aún requiere un $ terminación.

Francamente, dado lo anterior, creo que re.match() debe estar en desuso. Me interesaría saber las razones por las que debe conservarse.

puede consultar el siguiente ejemplo para comprender el funcionamiento de re.match y re.search

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

re.match no devolverá ninguno, pero re.search devolverá abc.

la coincidencia es mucho más rápida que la búsqueda, por lo que en lugar de hacer regex.search (“palabra”) puede hacer regex.match ((. *?) word (. *?)) y ganar toneladas de rendimiento si trabaja con millones de muestras

Este comentario de @ivan_bilan bajo la respuesta aceptada de arriba me hizo pensar si tal piratería realmente está acelerando algo, así que averigüemos cuántas toneladas de rendimiento realmente ganará.

Preparé el siguiente conjunto de pruebas:

 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) 

Hice 10 mediciones (1M, 2M, …, 10M palabras) que me dieron la siguiente ttwig:

Coincidir contra búsqueda regex trazo de línea speedtest

Las líneas resultantes son sorprendentemente (en realidad no tan sorprendentemente) rectas. Y la función de search es (ligeramente) más rápida dada esta combinación de patrones específica. La moraleja de esta prueba: Evite sobre-optimizar su código.

re.match intenta hacer coincidir un patrón al principio de la cadena . re.search intenta hacer coincidir el patrón a lo largo de la cadena hasta que encuentre una coincidencia.

Mucho más corto:

  • search escaneos a través de toda la cadena.

  • match hace solo principio de cuerda.

Siguiendo Ex lo dice:

 >>> a = "123abc" >>> re.match("[az]+",a) None >>> re.search("[az]+",a) abc