Функция re.match в Python: синтаксис и практические примеры
Основы re.match
Функция re.match в модуле re проверяет, совпадает ли начало строки с заданным шаблоном. Она возвращает объект совпадения (Match) в случае успеха или None при неудаче. Это базовый инструмент для валидации входных данных, парсинга первой части строки и разметки текста.
import re
pattern = r'\d{3}'
text = '123abc'
match = re.match(pattern, text)
if match:
print('Найдено:', match.group())
else:
print('Совпадений нет')любой символ python (любой символ в регулярных выражениях python)
Найдено: 123
Python re match (регулярное выражение re.match в python)
В примере шаблон r'\d{3}' ищет три цифры в начале строки. Функция match.group() возвращает совпавшую подстроку. Если бы строка начиналась с букв, результат был бы None.
Типичная ошибка: путаница с re.search, который ищет по всей строке, а не только с начала.
Решение: использовать re.match только если требуется совпадение именно в начале. В противном случае применяется re.search.
Как выполнить регистронезависимый поиск с re.match?
Флаг re.IGNORECASE (или сокращённо re.I) позволяет игнорировать регистр букв в шаблоне.
import re
pattern = r'hello'
text = 'Hello, world!'
match = re.match(pattern, text, re.I)
if match:
print('Совпадение:', match.group())
else:
print('Нет совпадения')
символы регулярных выражений python (символы регулярных выражений python)
Совпадение: Hello
Проблема: флаг забывают указать, и чувствительное к регистру выражение не срабатывает на строку, начинающуюся с заглавной буквы.
Решение: всегда явно передавать re.I в качестве третьего аргумента, если требуется нечувствительность к регистру.
Как извлечь группы из совпадения с помощью re.match?
Круглые скобки в шаблоне создают группы, доступные через методы group(), groups() или groupdict() для именованных групп.
import re
pattern = r'(\d{2})-(\d{2})-(\d{4})' # ДД-ММ-ГГГГ
text = '15-08-2023_event'
match = re.match(pattern, text)
if match:
print('День:', match.group(1))
print('Месяц:', match.group(2))
print('Год:', match.group(3))
print('Все группы:', match.groups())
День: 15
Месяц: 08
Год: 2023
Все группы: ('15', '08', '2023')
Именованные группы задаются синтаксисом (?P<имя>...).
pattern = r'(?P<day>\d{2})-(?P<month>\d{2})-(?P<year>\d{4})'
match = re.match(pattern, text)
if match:
print('Год:', match.group('year'))
print('Словарь:', match.groupdict())
Год: 2023
Словарь: {'day': '15', 'month': '08', 'year': '2023'}
Ошибка: обращение к несуществующей группе по номеру или имени вызывает исключение IndexError или IndexError (на самом деле KeyError для именованных).
Решение: перед извлечением проверять существование совпадения (if match:) и использовать корректные номера/имена.
Чем re.match отличается от re.search?
re.match проверяет только начало строки, а re.search просматривает всю строку на первое совпадение в любой позиции.
import re
pattern = r'\d+'
text = 'abc123'
mat = re.match(pattern, text)
sea = re.search(pattern, text)
print('re.match:', mat)
print('re.search:', sea.group() if sea else None)
re.match: None re.search: 123
В примере re.match возвращает None, так как строка не начинается с цифры, а re.search находит цифры в середине.
Путаница между этими функциями - самая частая ошибка начинающих.
Решение: для проверки полного соответствия строки шаблону (с начала до конца) используется re.fullmatch, для поиска в любом месте - re.search, для начала строки - re.match.
Как проверить полное соответствие строки шаблону через re.match?
re.match находит совпадение только в начале, но для полной проверки можно добавить якорь конца строки $.
import re
pattern = r'^\d{3}$' # строка должна состоять ровно из трёх цифр
texts = ['123', '123abc', ' 123']
for t in texts:
match = re.match(pattern, t)
print(f"'{t}': {match.group() if match else None}")
'123': 123 '123abc': None ' 123': None
Символ ^ в данном контексте не обязателен, так как re.match и так начинает с начала, но его часто добавляют для ясности. Якорь $ заставляет совпадение заканчиваться строго в конце строки.
Игнорирование пробелов: строка ' 123' не совпадает, хотя содержит цифры, - из-за начального пробела.
Решение: предварительно удалять пробелы (strip()) или использовать шаблон, допускающий пробелы, например r'^\s*\d{3}\s*$'.
Расширенные примеры использования re.match
Пример 1: работа с объектом Match после re.match
Объект совпадения предоставляет методы для извлечения позиции и длины совпадения.
import re
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})'
text = '2023-08-15'
match = re.match(pattern, text)
if match:
print('Совпадение:', match.group()) # весь совпавший текст
print('Начало:', match.start()) # 0
print('Конец:', match.end()) # 7
print('Диапазон:', match.span()) # (0, 7)
print('Год:', match.group('year'))
print('Месяц:', match[2]) # по номеру через квадратные скобки
Совпадение: 2023-08 Начало: 0 Конец: 7 Диапазон: (0, 7) Год: 2023 Месяц: 08
Метод match[номер] (Python 3.6+) альтернатива group().
Пример 2: перебор списка строк с re.match
Функция полезна для фильтрации записей, начинающихся с определённого префикса.
import re
lines = [
'ERROR: disk full',
'INFO: task completed',
'WARNING: low memory',
'ERROR: connection lost'
]
pattern = r'ERROR:(.*)'
errors = []
for line in lines:
match = re.match(pattern, line)
if match:
errors.append(match.group(1).strip())
print('Сообщения об ошибках:', errors)
Сообщения об ошибках: ['disk full', 'connection lost']
Используется группа (.*) для захвата всего оставшегося текста после префикса.
Пример 3: парсинг IP-адреса из лога с помощью re.match
Логи часто начинаются с IP-адреса. re.match извлекает его.
import re
log_line = '192.168.1.1 - - [10/Oct/2023] "GET /index.html"'
pattern = r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
match = re.match(pattern, log_line)
if match:
ip = match.group(1)
print('IP:', ip)
else:
print('IP не найден')
IP: 192.168.1.1
Шаблон захватывает четыре числа, разделённые точками. Обратите внимание, что шаблон не проверяет допустимый диапазон (0–255) - это можно сделать дополнительной валидацией.
Пример 4: компилированный шаблон для многократного использования
Компиляция регулярного выражения с помощью re.compile повышает производительность при повторных вызовах.
import re
pattern = re.compile(r'^\w+@\w+\.\w{2,3}$') # примитивный email
emails = ['user@example.com', 'invalid-email', 'test@test.org']
for email in emails:
match = pattern.match(email)
if match:
print(f"'{email}' валидный (начало)")
else:
print(f"'{email}' не валидный")
'user@example.com' валидный (начало) 'invalid-email' не валидный 'test@test.org' валидный (начало)
Метод pattern.match(string) эквивалентен re.match(pattern, string). Компиляция также позволяет задать флаги один раз.
Пример 5: re.match с обработкой None
Без проверки на None вызов group() вызовет AttributeError.
import re
def extract_first_number(text):
match = re.match(r'\d+', text)
if match is None:
return None
return int(match.group())
print(extract_first_number('42 ответ'))
print(extract_first_number('нет цифр'))
42 None
Такой подход безопасен и часто применяется в функциях.
Пример 6: re.match с флагом re.MULTILINE (особенности)
Флаг re.MULTILINE меняет поведение якорей ^ и $, но не влияет на re.match, так как последний всегда проверяет начало всей строки, а не каждой строки.
import re
text = """first line
second line
third line"""
pattern = r'^\w+'
match = re.match(pattern, text, re.MULTILINE)
print('re.match c MULTILINE:', match.group() if match else None)
# результат: 'first' (только первая строка)
re.match c MULTILINE: first
Для поиска в начале каждой строки следует использовать re.search или re.findall с флагом re.MULTILINE.
Пример 7: re.match для извлечения даты из начала строки
Совмещение групп и флагов для гибкого парсинга.
import re
log = '2023-10-05 14:30:00 ERROR something happened'
pattern = r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})'
match = re.match(pattern, log)
if match:
year, month, day, hour, minute, second = match.groups()
print(f'Дата: {day}.{month}.{year} {hour}:{minute}:{second}')
Дата: 05.10.2023 14:30:00
Метод groups() возвращает кортеж всех захваченных групп.