Регулярные выражения в Python

Регулярные выражения очень широко применяются при обработке строк для сравнения шаблонов. Язык Python, разумеется, имеет встроенную поддержку для работы с ними. Чтобы воспользоваться этими возможностями, необходимо импортировать модуль re.

import re

Теперь все готово для использования регулярных выражений.

Метод re.search()

Метод re.search() используется для нахождения первого вхождения заданного шаблона в строку.

Синтаксис: re.search(pattern, string, flags[optional])

Метод re.search() принимает на вход шаблон и строку и возвращает объект match в случае успеха, а в противном случае, если шаблон не был найден, возвращает None. Объект match имеет метод group(), который возвращает сам шаблон.

import re
s = "my number is 123"
match = re.search(r'\d\d\d', s)
match
<_sre.SRE_Match object; span=(13, 16), match='123'>
match.group()
'123'

В примере выше мы использовали шаблон \d\d\d. Шаблон \d в регулярных выражениях сравнивает единичные цифры, следовательно \d\d\d будет сравнивать цифры вида 111222786. Соответственно, цифры вида 121444 будут пропущены.

Основные шаблоны регулярных выражений

Символ Описание
. любой символ, за исключением новой строки
\w любой буквенный, цифровой символ, а также нижнее подчеркивание
\W любые не буквенные и не цифровые символы и не нижнее подчеркивание
\d любая одиночная цифра
\D любой одиночный символ, кроме цифры
\s любой пробельный символ, как например \n\t, а также сам пробел
\S любой не пробельный одиночный символ
[abc] любой одиночный символ в данном множестве, то есть в этом примере это либо  a, либо b, либо c
[^abc] любой одиночный символ, отличный от ab и c
[a-z] любой одиночный символ в диапазоне от a до z
[a-zA-Z] любой одиночный символ в диапазоне a-z или A-Z
[0-9] любой одиночный символ в диапазоне 09
^ сравнение начинается с начала строки
$ сравнение начинается с конца строки
+ один или больше символов (жадное соответствие).
* ноль или больше символов (жадное соответствие).

Рассмотрим еще один пример.

import re
s = "tim email is tim@somehost.com"
match = re.search(r'[\w.-]+@[\w.-]+', s)

# Приведенное выше регулярное выражение будет искать e-mail адрес

if match:
    print(match.group())
else:
    print("сравнений не обнаружено")

Ожидаемый результат

tim@somehost.com

Здесь мы использовали шаблон [\w.-]+@[\w.-]+ чтобы найти в строке соответствие с e-mail адресом. В случае успеха метод re.search() возвращает объект match, а уже при помощи метода этого объекта group() можно извлечь хранящийся там текст. В данном примере это tim@somehost.com.

Группровка выражений

Группировка выражений позволяет нам извлекать части из нужной строки. Создать группу можно при помощи круглых скобок (). Допустим, мы хотим извлечь отдельно имя пользователя и имя хоста из e-mail адреса, такого как в предыдущем примере. Для этого нам нужно заключить в разные скобки шаблон для имени и шаблон для хоста следующим образом:

match = re.search(r'([\w.-]+)@([\w.-]+)', s)

Обратите внимание: добавление скобок не означает изменение шаблона для поиска соответствия. Наш код по-прежнему ищет полное совпадение с заданным шаблоном. Если поиск увенчается успехом, match.group(1) будет соответствовать содержимому первых круглых скобок, а match.group(2) — содержимому вторых круглых скобок.

import re
s = "tim email is tim@somehost.com"
match = re.search('([\w.-]+)@([\w.-]+)', s)
if match:
    print(match.group()) ## tim@somehost.com (полное сравнение)
    print(match.group(1)) ## tim (the username, первая группа)
    print(match.group(2)) ## somehost (the host, вторая группа)

Функция findall()

Как вы уже знаете, функция re.search() находит только первое вхождение заданного шаблона в строку. А если мы хотим найти все вхождения, в дело вступает функция findall().

Синтаксис: findall(pattern, string, flags=0[optional])

В случае успеха данная функция возвращает список, в котором в виде строк содержатся все искомые вхождения по порядку. Если вхождений нет, то эта функция возвратит пустой список.

import re
s = "Tim's phone numbers are 12345-41521 and 78963-85214"
match = re.findall(r'\d{5}', s)

if match:
    print(match)

Ожидаемый результат:

['12345', '41521', '78963', '85214']

Функция findall() также позволяет использовать группировку выражений. Когда заданы скобочные группы, функция findall() возвращает список кортежей, в которых содержатся искомые соответствия. Следующий пример должен все окончательно прояснить.

import re
s = "Tim's phone numbers are 12345-41521 and 78963-85214"
match = re.findall(r'(\d{5})-(\d{5})', s)
print(match)

for i in match:
    print()
    print(i)
    print("Первая группа", i[0])
    print("Вторая группа", i[1])

Ожидаемый результат:

[('12345', '41521'), ('78963', '85214')]

('12345', '41521')
Первая группа 12345
Вторая группа 41521

('78963', '85214')
Первая группа 78963
Вторая группа 85214

Опциональные флаги

Обе функции, re.search() и re.findall(), могут принимать необязательные параметры — флаги. С их помощью можно слегка изменять поведение функции.

Флаги Описание
re.IGNORECASE При поиске соответствий будет игнорироваться регистр символов.
re.DOTALL Позволяет (.) искать символ новой строки. По умолчанию (.) ищет любой символ кроме символа новой строки.
re.MULTILINE Благодаря этому флагу ^ и $ будут означать начало и конец каждой строчки (line) в многострочной строке (string). По умолчанию эти символы означают начало и конец строки (string).

Использование функции re.match()

Функция re.match() очень похожа на функцию re.search(). Различие состоит лишь в том, что функция re.match() начинает поиск сравнений с начала строки.

import re
s = "python tuts"
match = re.match(r'py', s)
match_1 = re.match(r'th', s)
if match:
    print(match.group()) # выведет на экран 'py'
if match_1:
    print(match_1.group()) # не выведет на экран ничего

Того же можно достичь и с функцией re.search(), просто добавив ^ к шаблону сравнения.

import re
s = "python tuts"
match = re.search(r'^py', s)
match_1 = re.search(r'^th', s)
if match:
    print(match.group()) # выведет на экран 'py'
if match_1:
    print(match_1.group()) # не выведет на экран ничего

На этом мы завершаем знакомство с модулем re языка Python.