В чем разница между функциями search()
и match()
в Python re
module?
Я прочитал документацию ( текущая документация), но я никогда не помню его. Я продолжаю искать и переучивать его. Я надеюсь, что кто-то ясно ответит на это примерами, чтобы (возможно) это застряло у меня в голове. Или, по крайней мере, у меня будет лучшее место, чтобы вернуться с моим вопросом, и для его изучения потребуется меньше времени.
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
search
→ найти что-нибудь в строке и вернуть объект соответствия.
match
→ найти что-то в начале строки и вернуть объект соответствия.
re.search
поиск es для шаблона по всей строке, тогда как re.match
не ищет шаблон; если это не так, у него нет другого выбора, кроме match в начале строки.
fullmatch
в fullmatch
3.4)?
Разница заключается в том, что re.match()
вводит в заблуждение любого, кто привык к сопоставлению регулярных выражений Perl, grep или sed, а re.search()
- нет.: -)
Более трезвый, Как замечает Джон Д. Кук, re.match()
"ведет себя так, как если бы каждый шаблон имел" добавленный". Другими словами, re.match('pattern')
равно re.search('^pattern')
. Таким образом, он фиксирует левую сторону шаблона. Но он также не привязывает правую сторону шаблона: это все еще требует завершения $
.
Откровенно говоря, я сказал, что re.match()
должен быть устаревшим. Мне было бы интересно узнать причины, по которым его следует сохранить.
вы можете ссылаться на приведенный ниже пример, чтобы понять работу re.match и re.search
a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)
re.match не вернет none, но re.search вернет abc.
Соответствие выполняется намного быстрее, чем поиск, поэтому вместо выполнения 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
(немного) быстрее, учитывая эту конкретную комбинацию шаблонов. Мораль этого теста: избегайте чрезмерной оптимизации вашего кода.
match
все еще быстрее, чем функция search
если сравнить то же регулярное выражение. Вы можете проверить свой скрипт, сравнив re.search('^python', word)
с re.match('python', word)
(или re.match('^python', word)
который такой же, но легче понять, если вы не читаете документацию и, кажется, не влияет на производительность)
re.match пытается сопоставить шаблон в начале строки. re.search пытается сопоставить шаблон по всей строке, пока не найдет совпадение.
Намного короче:
search
сканирует всю строку.
match
Делает только начало строки.
После Ex говорит это:
>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc