Регулярное выражение Python — понимание разницы между совпадением и поиском

Из того, что я понял,

match: при наличии строки str и шаблона pat функция match проверяет, соответствует ли строка шаблону с начала строки str.

search: при наличии строки str и шаблона pat поиск проверяет, соответствует ли str шаблону из каждого индекса str.

Если да, то есть ли смысл использовать '^' в начале регулярного выражения с совпадением?

Насколько я понял, так как match уже проверяет с самого начала, то нет. Я, вероятно, ошибаюсь; где моя ошибка?


person user1413824    schedule 26.05.2012    source источник
comment
Вы читали это? docs.python.org/library/re.html#search-vs- совпадение. Это все объясняет.   -  person jamylak    schedule 26.05.2012
comment
Возможный дубликат В чем разница между re.search и повторить?   -  person olbinado11    schedule 26.02.2019


Ответы (3)


При вызове функции re.match символ ^ не имеет большого значения, поскольку эта функция начинает процесс сопоставления в начале строки. Однако он имеет значение для других функций в модуле re и при вызове match для скомпилированного объекта регулярного выражения.

Например:

text = """\
Mares eat oats
and does eat oats
"""

print re.findall('^(\w+)', text, re.MULTILINE) 

Это печатает:

['Mares', 'and']

С включенными re.findall() и re.MULTILINE он дает вам первое слово (без начального пробела) в каждой строке вашего текста.

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

Простой лексер/сканер как пример:

text = """\
Mares eat oats
and does eat oats
"""

pattern = r"""
(?P<firstword>^\w+)
|(?P<lastword>\w+$)
|(?P<word>\w+)
|(?P<whitespace>\s+)
|(?P<other>.)
"""

rx = re.compile(pattern, re.MULTILINE | re.VERBOSE)

def scan(text):
    pos = 0
    m = rx.match(text, pos)
    while m:
        toktype = m.lastgroup
        tokvalue = m.group(toktype)
        pos = m.end()
        yield toktype, tokvalue
        m = rx.match(text, pos)

for tok in scan(text):
    print tok

который печатает

('firstword', 'Mares')
('whitespace', ' ')
('word', 'eat')
('whitespace', ' ')
('lastword', 'oats')
('whitespace', '\n')
('firstword', 'and')
('whitespace', ' ')
('word', 'does')
('whitespace', ' ')
('word', 'eat')
('whitespace', ' ')
('lastword', 'oats')
('whitespace', '\n')

Это различает типы слов; слово в начале строки, слово в конце строки и любое другое слово.

person Matt Anderson    schedule 26.05.2012

Я считаю, что нет никакой пользы. Следующее копируется/вставляется с: http://docs.python.org/library/re.html#search-vs-match

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

Например:

>>> re.match("c", "abcdef")  # No match
>>> re.search("c", "abcdef") # Match
<_sre.SRE_Match object at ...>

Регулярные выражения, начинающиеся с '^', можно использовать с search(), чтобы ограничить совпадение в начале строки:

>>> re.match("c", "abcdef")  # No match
>>> re.search("^c", "abcdef") # No match
>>> re.search("^a", "abcdef")  # Match
<_sre.SRE_Match object at ...>

Однако обратите внимание, что в режиме MULTILINE match() соответствует только началу строки, тогда как использование search() с регулярным выражением, начинающимся с '^', будет соответствовать началу каждой строки.

>>> re.match('X', 'A\nB\nX', re.MULTILINE)  # No match
>>> re.search('^X', 'A\nB\nX', re.MULTILINE)  # Match
<_sre.SRE_Match object at ...>
person jamylak    schedule 26.05.2012
comment
так что ^ в начале регулярного выражения с совпадением бессмысленно, верно? - person user1413824; 26.05.2012
comment
Ну, сам символ можно использовать для других вещей, например, в [^\w], но я не вижу в нем никакого смысла для проверки начала. - person jamylak; 26.05.2012

В обычном режиме вам не нужен ^, если вы используете match. Но в многострочном режиме (re.MULTILINE) это может быть полезно, потому что ^ может соответствовать не только началу всей строки, но и началу каждой строки.

person chys    schedule 26.05.2012
comment
так что re.MULTILINE не имеет смысла без ^ при запуске? - person user1413824; 26.05.2012
comment
@user1413824 user1413824 Похоже, да, за исключением того, что $ тоже затронут. Согласно документам Python, все, что делает re.MULTILINE, — это изменяет значения ^ и $. - person chys; 30.07.2012