В чем разница между re.search и re.match? - PullRequest
426 голосов
/ 08 октября 2008

В чем разница между функциями search() и match() в модуле Python re ?

Я прочитал документацию ( текущую документацию ), но, похоже, я ее никогда не помню. Я продолжаю искать его и заново изучать. Я надеюсь, что кто-то ответит на это ясно с примерами, так что (возможно) это застрянет в моей голове. Или, по крайней мере, у меня будет лучшее место, чтобы вернуться с моим вопросом, и для его изучения потребуется меньше времени.

Ответы [ 8 ]

431 голосов
/ 08 октября 2008

re.match закрепляется в начале строки. Это не имеет ничего общего с символами новой строки, поэтому это не то же самое, что использование ^ в шаблоне.

Как указано в документации re.match :

Если ноль или более символов на начало строки соответствует шаблону регулярного выражения, возвращает соответствующий MatchObject экземпляр. Вернуть None, если строка не соответствовать шаблону; обратите внимание, что это отличается от совпадения нулевой длины.

Примечание: если вы хотите найти совпадение в любом месте строки используйте search() вместо этого.

re.search ищет всю строку, так как документация гласит :

Сканирование через строку в поисках место, где регулярное выражение шаблон производит совпадение и возвращает соответствующий MatchObject экземпляр. Вернуть None, если в строка соответствует шаблону; Обратите внимание, что это отличается от поиска совпадение нулевой длины в некоторой точке строка.

Так что, если вам нужно сопоставить начало строки или полностью всю строку, используйте match. Это быстрее. В противном случае используйте search.

В документации есть специальный раздел для match против search, который также охватывает многострочные строки:

Python предлагает два разных примитива операции на основе регулярного выражения: match проверяет совпадение только в начале строки, пока search проверяет совпадение везде в строке (вот что Perl делает по умолчанию).

Обратите внимание, что match может отличаться от search даже при использовании регулярного выражения начиная с '^': '^' только совпадения в начале строки или в MULTILINE режим также сразу после новой строки. «match» операция завершается успешно , только если шаблон соответствует началу строки независимо от режима или при запуске позиция, заданная необязательным pos аргумент независимо от того, является ли Новая строка предшествует ему.

Теперь достаточно разговоров. Время посмотреть пример кода:

# 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
82 голосов
/ 31 декабря 2011

search & rArr; найти что-нибудь в строке и вернуть соответствующий объект.

match & rArr; найдите что-то в начале строки и верните соответствующий объект.

46 голосов
/ 08 октября 2008

re.search поиск es для шаблона по всей строке , тогда как re.match не не ищет шаблон; если это не так, у него нет другого выбора, кроме сопоставления в начале строки.

25 голосов
/ 21 мая 2016

Разница в том, что re.match() вводит в заблуждение любого, кто привык к Perl , grep или sed сопоставлению регулярного выражения, а re.search() нет. : -)

Трезвее, Как замечает Джон Д. Кук , re.match() "ведет себя так, как если бы каждый шаблон был ^ добавлен". Другими словами, re.match('pattern') равно re.search('^pattern'). Таким образом, он закрепляет левую сторону шаблона. Но он также не привязывает правую сторону шаблона: , который все еще требует завершения $.

Честно говоря, с учетом вышесказанного, я думаю, re.match() следует считать устаревшим. Мне было бы интересно узнать причины, по которым его следует сохранить.

24 голосов
/ 07 апреля 2018

сопоставление выполняется намного быстрее, чем поиск, поэтому вместо выполнения regex.search ("word") вы можете выполнить regex.match ((. *?) Word (. *?)) И получить массу производительности, если вы работаете с миллионами образцов.

Этот комментарий @ivan_bilan под принятым ответом выше заставил меня задуматься о том, действительно ли такой хак действительно ускоряет что-либо, поэтому давайте выясним, сколько тонн производительности вы действительно получите .

Я подготовил следующий набор тестов:

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)

Я сделал 10 измерений (1M, 2M, ..., 10M слов), что дало мне следующий график:

match vs. search regex speedtest line plot

Результирующие строки на удивление (на самом деле не так уж и удивительно) прямые. И функция search (немного) быстрее , учитывая эту конкретную комбинацию паттернов. Мораль этого теста: Избегайте чрезмерной оптимизации вашего кода.

24 голосов
/ 30 июля 2015

Вы можете обратиться к приведенному ниже примеру, чтобы понять работу re.match и re.search

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

re.match не вернет ничего, но re.search вернет abc.

14 голосов
/ 08 октября 2008

re.match пытается сопоставить шаблон в начале строки . re.search пытается сопоставить шаблон по всей строке , пока не найдет совпадение.

1 голос
/ 31 октября 2018

намного короче:

  • search сканирует всю строку.

  • match Только начало строки.

После Экс говорит:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...