Qual é a diferença entre re.search e re.match?
Pergunta
Qual é a diferença entre as funções search()
e match()
na Python re
módulo ?
Eu li o documentação (< a href = "http://docs.python.org/2/library/re.html?highlight=matching%20searching#search-vs-match" rel = "noreferrer"> documentação atual ), mas eu nunca parecem se lembrar dela. Eu continuo a ter que procurá-lo e re aprender-lo. Eu estou esperando que alguém vai responder-lhe claramente com exemplos para que (talvez) ele vai ficar na minha cabeça. Ou pelo menos eu vou ter um lugar melhor para voltar com a minha pergunta e vai demorar menos tempo para re-aprender.
Solução
re.match
está ancorado no início da cadeia. Isso não tem nada a ver com novas linhas, por isso não é o mesmo que usar ^
no padrão.
Como o documentação re.match diz:
Se zero ou mais caracteres no início da cadeia coincidir com o padrão de expressão regular, retornar um exemplo
MatchObject
correspondente. VoltarNone
se a cadeia não faz corresponder ao padrão; note que este é diferente de um jogo de comprimento zero.Nota: Se você quiser localizar uma correspondência em qualquer lugar corda,
search()
uso em seu lugar.
pesquisas re.search
toda a cadeia, como a documentação diz :
Verificar através de cordas à procura de um local onde a expressão regular padrão produz uma partida, e regresso a exemplo
MatchObject
correspondente. RetornoNone
se nenhuma posição no corda corresponde ao padrão; Observe que isso é diferente de encontrar uma jogo de comprimento zero em algum ponto no string.
Então, se você precisa combinar no início da string, ou para combinar todo o match
uso string. É mais rápido. Caso contrário, use search
.
A documentação tem um href="http://docs.python.org/2/library/re.html#search-vs-match" seção específica para match
vs. search
, que também abrange cordas de várias linhas:
Python oferece dois diferentes primitiva operações com base em comum expressões: verificações
match
para uma partida apenas no início da cadeia, enquanto os chequessearch
para uma partida em qualquer lugar na cadeia (isto é o que Perl faz por padrão).Note que
match
podem diferirsearch
mesmo quando se usa uma expressão regular começando com'^'
:'^'
corresponde apenas no início da string, ou em ModoMULTILINE
também imediatamente após uma nova linha. O “match
” operação for bem-sucedido somente se o padrão partidas no start da string independentemente do modo, ou na partida posição determinada pelopos
opcional argumento independentemente de um precede nova linha-lo.
Agora, chega de conversa. Tempo para ver um exemplo de código:
# 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
Outras dicas
search
? encontrar algo em qualquer lugar na string e retornar um objeto jogo.
match
? encontrar algo no início da string e retornar um objeto jogo.
re.search
Pesquisar es para o padrão em toda a cadeia , enquanto re.match
faz não procurar o padrão; se isso não acontecer, ele não tem outra escolha senão a jogo -lo no início da string.
você pode consultar o exemplo abaixo para entender o funcionamento do re.match e re.search
a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)
re.match retornará nenhum, mas re.search voltará abc.
A diferença é, engana re.match()
qualquer um acostumado a Perl , grep ou sed de expressões regulares, e re.search()
não . : -)
Mais sobriamente, Como John D. Cook observa , re.match()
"se comporta como se cada padrão tem ^ prefixado." Em outras palavras, re.match('pattern')
igual re.search('^pattern')
. Por isso, ancora lado esquerdo de um padrão. Mas também não ancorar lado direito de um padrão:. que ainda requer um $
terminação
Francamente dada a acima, eu acho que re.match()
deve ser substituído. Eu estaria interessado em saber razões, deve ser mantida.
jogo é muito mais rápido do que a busca, então ao invés de fazer regex.search ( "palavra") você pode fazer Regex.Match ((. *?) Palavra (. *?)) E toneladas de ganho de desempenho se você estiver trabalhando com milhões de amostras.
Este comentário de @ivan_bilan sob a resposta aceita acima me fez pensar se tal corte é realmente acelerando qualquer coisa, então vamos descobrir quantas toneladas de desempenho que você vai realmente ganho.
Eu preparei o seguinte conjunto de testes:
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)
Eu fiz 10 medições (1M, 2M, ..., palavras 10M) que me deu o seguinte gráfico:
As linhas resultantes são surpreendentemente (na verdade, não que, surpreendentemente,) de cadeia linear. E o Função search
é (ligeiramente) mais rápido dada esta combinação padrão específico. A moral deste teste:. Evite overoptimizing seu código
tentativas re.match para corresponder a um padrão no início da string . tentativas re.search para corresponder ao padrão em toda a cadeia até encontrar uma correspondência.
Muito mais curto:
-
search
scans trough seqüência inteira. -
match
A única início da string.
A seguir Ex diz que:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc