Вопрос

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

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

Это было полезно?

Решение

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

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

  

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

     

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

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

  

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

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

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

  

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

     

Обратите внимание, что match может отличаться от search   даже при использовании регулярного выражения   начиная с '^' : только '^'   в начале строки или в   Режим MULTILINE также сразу   после новой строки. & # 8220; match & # 8221;   Операция завершается , только если шаблон   соответствует началу строки   независимо от режима или при запуске   позиция, заданная необязательным 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

Другие советы

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

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

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

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

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

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

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

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

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

  

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

 соответствие по сравнению с поисковым регулярным выражением линейного сюжета

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

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

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

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

  • match Выполняет только начало строки.

Следующий Бывший говорит об этом:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top