Después de de nuestra prolongada recopilación de datos pudimos resolver este atolladero que pueden tener muchos usuarios. Te regalamos la solución y nuestro deseo es serte de mucha ayuda.
Solución:
re.match
está anclado al principio de la string. Eso no tiene nada que ver con los saltos de línea, 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 en el
comienzo de string coincide con el patrón de expresión regular, devuelve un correspondienteMatchObject
ejemplo. RegresoNone
Si el string 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 stringutilizar
search()
en lugar de.
re.search
busca en todo stringcomo dice la documentación:
Escanear a través string buscando una ubicación donde el patrón de expresión regular produzca una coincidencia y devuelva un correspondiente
MatchObject
ejemplo. RegresoNone
si no hay posición en el
string 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
string.
Entonces, si necesita hacer coincidir al comienzo de la stringo para hacer coincidir todo el string utilizar match
. Es mas rapido. De lo contrario, use search
.
La documentación tiene un apartado específico para match
contra search
que también cubre cadenas multilínea:
Python ofrece dos operaciones primitivas diferentes basadas en expresiones regulares:
match
cheques para una coincidencia
solo al principio de El stringtiemposearch
cheques para una coincidencia
en cualquier sitio en el string (esto es lo que hace Perl por defecto).Tenga en cuenta que
match
puede diferir desearch
incluso cuando se usa una expresión regular que comienza con'^'
:'^'
partidos sólo al comienzo de la stringo en
MULTILINE
modo también inmediatamente después de una nueva línea. Los “match
” operación exitosa sólo si el patrón coincide en el comienzo de El stringindependientemente del modo, o en la posición inicial dada por el opcional
pos
argumento independientemente de si un salto de línea lo precede.
Ahora, suficiente charla. Es hora de ver un 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 del string y devolver un objeto de coincidencia.
match
⇒ encontrar algo en el comenzando de El string y devolver un objeto de coincidencia.
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((.*?)palabra(.*?)) y obtener toneladas de rendimiento si está trabajando con millones de muestras
Este comentario de @ivan_bilan bajo la respuesta aceptada anterior me hizo pensar si tal cortar a tajos en realidad está acelerando cualquier cosa, así que averigüemos cuántas toneladas de rendimiento obtendrá realmente.
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 gráfica:
Las líneas resultantes son sorprendentemente (en realidad no tan sorprendentemente) rectas. Y el search
la función es (ligeramente) más rápida dada esta combinación específica de patrones. La moraleja de esta prueba: Evite sobreoptimizar su código.