Методы match(), split(), sub(), subn(), compile()

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Смотреть материал на YouTube | RuTube

На этом занятии продолжим рассматривать методы модуля 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>

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

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

Обратите внимание, в строке замены 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>

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

def counter(start=0):
    def repl_find(m):
        nonlocal start
        start += 1
        return f"<option value='{start}'>{m.group(1)}</option>\n"
    return repl_find

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

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

lst = re.sub(r"\s*(\w+)\s*", counter(), text)

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

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

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

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

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

re.compile

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

re.compile(pattern, flags)

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

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

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

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

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

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

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

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Видео по теме