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.

Foi útil?

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. Voltar None 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. Retorno None 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 cheques search para uma partida em qualquer lugar na cadeia (isto é o que Perl faz por padrão).

Note que match podem diferir search mesmo quando se usa uma expressão regular começando com '^': '^' corresponde apenas no início da string, ou em Modo MULTILINE 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 pelo pos 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:

 busca jogo vs. regex gráfico de linha speedtest

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top