В чем разница между re.search и re.match?

366

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

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

Теги:
match
search

8 ответов

418
Лучший ответ

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

Как сообщает документация re.match:

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

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

re.search выполняет поиск по всей строке, поскольку в документации указано:

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

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

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

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

Обратите внимание, что match может отличаться от searchдаже при использовании регулярного выражения начиная с '^': '^' соответствует только в начале строки или в MULTILINE также сразу после новой строки. "match" операция выполняется только в том случае, если шаблон совпадает со строкой startнезависимо от режима, или при запуске положение, заданное опционным 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
  • 0
    Как насчет строк, содержащих переводы строки?
  • 0
    даже со строками, содержащими символы новой строки, match () совпадает только в НАЧАЛЕ строки.
Показать ещё 6 комментариев
71

search → найти что-нибудь в строке и вернуть объект соответствия.

match → найти что-то в начале строки и вернуть объект соответствия.

46

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

  • 4
    Почему совпадение в начале, но не до конца строки ( fullmatch в fullmatch 3.4)?
23

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

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

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

  • 3
    "ведет себя так, как будто каждый шаблон имеет ^ предваряющий." Истинно, только если вы не используете многострочный параметр. Правильное утверждение "... имеет \ A в начале"
22

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

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

re.match не вернет none, но re.search вернет abc.

  • 3
    Просто хотел бы добавить, что поиск вернет объект _sre.SRE_Match (или None, если не найден). Чтобы получить 'abc', вам нужно вызвать t.group ()
16

Соответствие выполняется намного быстрее, чем поиск, поэтому вместо выполнения 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 слов), что дало мне следующий график:

Изображение 4734

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

  • 3
    +1 за фактическое исследование предположений, лежащих в основе заявления, которое должно быть принято за чистую монету - спасибо.
  • 0
    Действительно, комментарий @ivan_bilan выглядит неправильно, но функция match все еще быстрее, чем функция search если сравнить то же регулярное выражение. Вы можете проверить свой скрипт, сравнив re.search('^python', word) с re.match('python', word) (или re.match('^python', word) который такой же, но легче понять, если вы не читаете документацию и, кажется, не влияет на производительность)
Показать ещё 5 комментариев
14

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

0

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

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

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

После Ex говорит это:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню