Методы re.match, re.split, re.sub, re.subn, re.compile

На этом занятии продолжим рассматривать методы модуля re для работы с регулярными выражениями.

re.match

И следующий метод

re.match(pattern, string, flags)

который определяет совпадение шаблона pattern в начале строки string с учетом флагов flags (если они указаны). Обратите внимание, в отличие от метода search, который ищет совпадение шаблона в любом месте строки, метод match смотрим совпадение только вначале. Он возвращает объект совпадения re.Match, либо значение None, если шаблон не был найден.

Рассмотрим такой пример. Пусть в строке ожидается номер телефона в формате:

+7(xxx)xxx-xx-xx

где x – любая цифра. Нужно проверить и извлечь данный формат. Для этого пропишем следующее правило:

import re
 
text = "+7(123)456-78-90"
m = re.match(r"\+7\(\d{3}\)\d{3}-\d{2}-\d{2}", text)
print(m)

При запуске программы получим объект совпадения:

<re.Match object; span=(0, 16), match='+7(123)456-78-90'>

Но, если вначале строки добавить любой символ, то совпадение найдено не будет, т.к. метод match выполняет анализ только сначала строки.

re.split

Следующий метод

re.split(pattern, string, flags)

выполняет разбивку строки string по заданному шаблону pattern. Например, у нас имеется вот такой многострочный текст:

text = """<point lon="40.8482" lat="52.6274" />
<point lon="40.8559" lat="52.6361" />; <point lon="40.8614" lat="52.651" />
<point lon="40.8676" lat="52.6585" />, <point lon="40.8672" lat="52.6626" />
"""

Требуется получить множество строк, которые разделяются между собой или переносом строки (\n), или символами ; и ,. Воспользуемся методом split со следующим шаблоном:

ar = re.split(r"[\n;,]+", text)
print(ar)

На выходе получим список из следующих строк:

['<point lon="40.8482" lat="52.6274" />', '<point lon="40.8559" lat="52.6361" />', ' <point lon="40.8614" lat="52.651" />', '<point lon="40.8676" lat="52.6585" />', ' <point lon="40.8672" lat="52.6626" />', '']

re.sub и re.subn

Следующий метод

re.sub(pattern, repl, string, count, flags)

  • pattern – регулярное выражение;
  • repl – строка или функция для замены найденного выражения;
  • string – анализируемая строка;
  • count – максимальное число замен (если не указано, то неограниченно);
  • flags – набор флагов (по умолчанию не используются).

Выполняет замену в строке найденных совпадений строкой или результатом работы функции repl и возвращает преобразованную строку.

В качестве примера с помощью метода sub преобразуем вот такой текст:

text = """Москва
Казань
Тверь
Самара
Уфа"""

в список формата HTML:

<option>Москва</option>
<option>Казань</option>
<option>Тверь</option>
<option>Самара</option>
<option>Уфа</option>

Для этого запишем вот такой шаблон и следующим параметром порядок замены найденных вхождений:

list = re.sub(r"\s*(\w+)\s*", r"<option>\1</option>\n", text)
print(list)

Обратите внимание, в строке замены repl мы можем использовать ссылки на сохраняющие группы. В данном случае ссылка \1 содержит выделенный город из текста. Затем эта строка окаймляется тегами <option>\1</option> и получается искомый список.

Но, кроме строки можно передавать ссылку на функцию, которая должна возвращать строку, подставляемую вместо найденного вхождения. Например, добавим тегам option атрибут value:

<option value='1'>Москва</option>
<option value='2'>Казань</option>
<option value='3'>Тверь</option>
<option value='4'>Самара</option>
<option value='5'>Уфа</option>

Для этого вначале определим функцию:

count = 0
def replFind(m):
    global count
    count += 1
    return f"<option value='{count}'>{m.group(1)}</option>\n"

В качестве параметра она принимает ссылку на объект re.Match, в котором хранится информация о найденном совпадении. И далее формируется строка с атрибутом value, причем, значение этого атрибута каждый раз увеличивается на 1.

Укажем ссылку на эту функцию в методе sub:

list2 = re.sub(r"\s*(\w+)\s*", replFind, text)

Все, теперь при каждой замене будет вызываться функция replFind и возвращать сформированную строку.

Аналогично работает и метод

subn(pattern, repl, string, count, flags)

Только он возвращает не только преобразованную строку, но и число произведенных замен:

list, total = re.subn(r"\s*(\w+)\s*", r"<option>\1</option>\n", text)
print(list, total)

re.compile

Последний метод, который мы рассмотрим в модуле re – это

re.compile(pattern, flags)

который выполняет компиляцию регулярного выражения и возвращает его в виде экземпляра класса Pattern.

Компиляция регулярного выражения выполняется, если один и тот же шаблон используется многократно. Например, нашу предыдущую программу можно записать так:

text = """Москва
Казань
Тверь
Самара
Уфа"""
 
count = 0
def replFind(m):
    global count
    count += 1
    return f"<option value='{count}'>{m.group(1)}</option>\n"
 
rx = re.compile(r"\s*(\w+)\s*")
list, total = rx.subn(r"<option>\1</option>\n", text)
list2 = rx.sub(replFind, text)
print(list, total, list2, sep="\n")

Смотрите, мы здесь сначала скомпилировали шаблон и сохранили ссылку rx на класс Pattern. Затем, уже из него вызываем методы subn и sub, но без указания регулярного выражения, так как эти методы мы вызываем не из модуля re, а из класса Pattern. В нем они переопределены так, чтобы не писать шаблон, который уже известен.

В общем случае, класс Pattern имеет все те же методы, что мы рассмотрели на этом и предыдущем занятиях модуля re и несколько уникальных свойств:

  • flags – возвращает список флагов, которые были установлены при компиляции;
  • pattern – строка исходного шаблона;
  • groupindex – словарь, ключами которого являются имена сохраняющих групп, а значениями – номера групп (пустой, если имена не используются).

Вот так можно оперировать регулярными выражениями через методы модуля re.