📌 Больше полезных статей по информатике и программированию вы можете найти у нас на сайте.
📢 Следить за новостями мира информатики, а также общаться, делиться впечатлениями и готовиться к экзаменам лучше вместе, в нашем Telegram-канале.
Что такое регулярные выражения
Представьте себе ситуацию, в которой вам присылают текстовый документ, где нужно найти определённые повторяющиеся слова. Допустим, в этом документе ошибочно была написана не та почта: вместо info@future-step.ru везде указана support@future-step.ru.
Как выйти из этой ситуации и заменить почтовый адрес на нужный? Конечно, вы можете просто воспользоваться уже знакомым поиском в любом текстовом редакторе и заменить все встреченные слова.
Но что будет, если этот документ составлен на английском, в котором слово support вполне может встречаться в тексте, а не только в почтовом адресе?
Или можем рассмотреть другую ситуацию. У нас есть большой документ с данными пользователей. Из него нужно извлечь все телефонные номера и сохранить в отдельный файл.
В таких случаях логично будет составить небольшую программу, которая и реализует весь функционал. Но как вы будете обрабатывать все эти последовательности символов? Не будете же вы в тексте циклично перебирать все цифры, чтобы найти телефонные номера?
Здесь вам на помощь придут регулярные выражения!
Под регулярными выражениями понимаются определённые последовательности символов, которые задают шаблон для поиска в тексте. Такие универсальные текстовые шаблоны регулярных выражений сами по себе напоминают миниатюрный язык программирования, предназначенный для описания и разбора текста.
При грамотном использовании регулярные выражения позволяют упросить задачи обработки текста, а также обеспечить решение многих задач, которые вообще не могли бы решиться без регулярных выражений.
Вам может потребоваться несколько десятков строк программного кода, чтобы извлечь, например, адреса электронной почты из файла. При этом такой код будет сложно сопровождать и как-либо менять, в случае смены даже малейших условий поиска. Однако с применением регулярных выражений решение такой задачи может быть реализовано всего за пару строк.
Для работы с регулярными выражениями в Python используется встроенный модуль re. В этой статье мы разберем некоторые наиболее полезные функции модуля re.
Но не переживайте, мы уже готовим подробнейший курс по регулярным выражениям в Python, где будут подробно описаны все возможности модуля re и продемонстрированы различные подходы к решению задач с использованием регулярных выражений.
Прежде чем перейти к изучению функций, давайте еще раз проговорим терминологию, которая будет использована далее. Итак, строкой мы будем называть какой-либо текст, в котором будет искать подстроку (символ или несколько символов), соответствующую заданному шаблону.
В дальнейшем при рассмотрении синтаксиса мы узнаем, что множество символов используют знак «\», который в Python экранирует символы строки. Чтобы избежать ненужного экранирования, мы будем использовать «сырые строки» (это которые с символом r в начале строки).
Функции модуля re
Рассмотрим первую и самую базовую функцию для работы с регулярными выражениями – match(). Данная функция находит совпадения только, если соответствующая шаблону подстрока находится в начале строки, по которой ведется поиск.
Функция match()
Функция match(), как и большинство функций в модуле re, имеет следующий синтаксис:
Давайте проверим работу этой функции и выведем на экран результат, который она вернет:
Мы видим, что функция нам возвращает match-объект, то есть результат успешного сопоставления регулярного выражения с текстом. Эти объекты содержат информацию о найденном совпадении, включая позицию в тексте, найденные группы и другие детали.
Рассмотрим некоторые методы match-объектов. Для того чтобы вывести найденную подстроку, можно воспользоваться методом group().
Можно сказать, работа метода group() аналогична __getitem__(), так что вы можете пользоваться синтаксисом обращения к элементу последовательности через квадратные скобки, а также перебирать все группы match-объекта в цикле (при их наличии).
Ещё одним полезным методом является span(), который возвращает кортеж из индексов начала и конца вхождения найденной подстроки в исходную строку.
Получить отдельно индекс начала или конца вхождения можно методами start() и end(), соответственно.
Функция search()
Но нам не всегда требуется найти совпадение лишь с началом строки. В таком случае можно использовать функцию search(), которая ищет совпадение с шаблоном по всему тексту, а не только по началу строки. Она находит только первое вхождение шаблона в строку.
Функция finditer()
Ещё одной полезной функцией, возвращающей match-объект, является finditer(). Функция finditer() ищет все непересекающиеся совпадения регулярного выражения в строке. Она возвращает итератор, содержащий в себе match-объекты каждого найденного совпадения.
Помните, что итераторы используются для «ленивых» вычислений: каждое совпадение в строке ищется «на лету» при итерации.
Давайте в строке «ABBAACABAABABCA» найдём все непересекающиеся вхождения подстрок «AB»:
Визуализируем это на изображении ниже:
Функция findall()
Некоторые функции рассматриваемого модуля не возвращают match-объект. К таким относится, например, функция findall(). Суть её работы очень похожа на функцию finditer(). Только в отличие от последней, findall() возвращает список строк или кортежей, содержащих найденные совпадения.
С этим связаны и другие особенности работы данной функции:
- Нет возможности получать информацию от позиции совпадения
- С готовым списком совпадений проще работать, но его формирование занимает определённое время, в отличие от «ленивых» вычислений у finditer()
Применим эту функцию к строке из прошлого примера:
Функция sub()
В модуле re есть некоторые функции, работа которых схожа с методами строк в Python. Например, функция sub() позволяет осуществлять замену подстроки, соответствующую заданному шаблону, в тексте.
Функция имеет такой синтаксис:
Используемые параметры обозначают следующее:
- pattern: шаблон регулярного выражения
- repl: строка или функция для замены
- string: строка для поиска
- count: максимальное количество замен
- flags: дополнительные флаги
Для примера давайте заменим в строке ниже два первых слова «шаг» на три символа «*»:
Функция split()
Также модуле re есть функция split(), работа которой похожа на работу одноимённого метода строк: исходная строка разделяется по заданному шаблону и функция возвращает список полученных частей.
Здесь добавляется еще один параметр – maxsplit, который отвечает за максимальное количество разбиений.
Синтаксис рассматриваемой функции будет таким:
В качестве примера рассмотрим строку «AAABACBABCABAAAC», которую разделим по паре символов «AB».
При этом ограничим количество разбиений maxsplit значением 2. В таком случае, после работы функции split() будем иметь список из трёх строк: «AAA», «BACBA» и «BCABAAAC».
В коде это можно записать так:
Во всех примерах выше мы искали подстроки, составленные из обычных символов. Но мы же раньше говорили про универсальность регулярных выражений, где же она скрывается?
Вся суть регулярных выражений скрыта в особом синтаксисе, который состоит из метасимволов, квантификаторов и скобочных групп. Давайте подробнее познакомимся с ними в следующей статье.