Функция 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() возвращает кортеж всех захваченных групп.

Регулярное выражение re.match в Python - comments

En
Python re match (python)