Регулярные выражения в Python
В Python для работы с регулярными выражениями есть модуль re
. Для использования его нужно импортировать. Рассмотрим простой пример поиска номера телефона:
>>> import re >>> match = re.search('\d{3}-\d{3}-\d{4}', 'Мой номер 495-456-9102') >>> print('Найденный телефонный номер: ' + match.group()) Найденный телефонный номер: 495-456-9102
Если найдены совпадения, метод re.search()
возвращает объект Match
. Если совпадений нет — None
.
Методы, которые предоставляет библиотека re
:
re.match(pattern, string, [flags=0])
re.search(pattern, string, [flags=0])
re.findall(pattern, string, [flags=0])
re.split(pattern, string, [maxsplit=0], [flags=0])
re.sub(pattern, replace, string, [count=0], [flags=0])
re.compile(pattern, [flags=0])
Список метасимволов, которые поддерживает модуль re
:
. ^ $ * + ? { } [ ] | ( )
Назначение метасимволов
.
— Один любой символ, кроме новой строки\n
?
— 0 или 1 вхождение шаблона слева+
— 1 и более вхождений шаблона слева*
— 0 и более вхождений шаблона слева\w
— Любая цифра или буква (\W
— все, кроме буквы или цифры)\d
— Любая цифра от 0 до 9 (\D
— все, кроме цифры)\s
— Любой пробельный символ (\S
— любой непробельнй символ)\b
— Граница слова[…]
— Один из символов в скобках ([^…]
— любой символ, кроме тех, что в скобках)\
— Экранирование специальных символов (\.
означает точку или\+
— знак «плюс»)^
и$
— Начало и конец строки соответственно{n,m}
— Отn
доm
вхождений ({n,}
—n
и больше)a|b
— Соответствуетa
илиb
(…)
— Группирует выражение и возвращает найденный текст\t,\n
— Символ табуляции и новой строки соответственно
Создание групп с помощью круглых скобок:
>>> match = re.search('(\d{3})-(\d{3}-\d{4})', 'Мой номер 495-456-9102') >>> match.group() '495-456-9102' >>> match.group(0) '495-456-9102' >>> print('Код города: ' + match.group(1)) Код города: 495 >>> print('Номер телефона: ' + match.group(2)) Номер телефона: 456-9102
Если нужно извлечь сразу все группы:
>>> match = re.search('(\d{3})-(\d{3}-\d{4})', 'Мой номер 495-456-9102') >>> match.groups() ('495', '456-9102') >>> code, number = match.groups() >>> code '495' >>> number '456-9102'
Метод re.search()
находит только первое вхождение шаблона. Если нужно найти все вхождения, используйте метод re.findall()
:
>>> matches = re.findall('\d{3}-\d{3}-\d{4}', 'Домашний 495-456-9102 или мобильный 926-123-4567') >>> matches ['495-456-9102', '926-123-4567']
Поиск всех групп для всех совпадений шаблона:
>>> matches = re.findall('(\d{3})-(\d{3}-\d{4})', 'Домашний 495-456-9102 или мобильный 926-123-4567') >>> matches [('495', '456-9102'), ('926', '123-4567')] >>> matches[0][0] '495' >>> matches[1][1] '123-4567'
Метод re.split()
разделяет строку по заданному шаблону:
>>> re.split('\n', 'First line.\nSecond line.\nThird line.') ['First line.', 'Second line.', 'Third line.']
Метод re.sub()
ищет шаблон в строке и заменяет его на указанную подстроку. Если шаблон не найден, строка остается неизменной.
>>> re.sub('RoboCop', 'Робот-полицейский', 'RoboCop is part man, part machine, all cop.') 'Робот-полицейский is part man, part machine, all cop.'
В строке замены можно использовать обратные ссылки \1
, \2
, \3
и т.д.
>>> re.sub('(\d{3})-(\d{3}-\d{4})', 'код города \\1, номер телефона \\2', 'Мой номер: 495-456-9102') 'Мой номер: код города 495, номер телефона 456-9102'Метод
re.match()
ищет по заданному шаблону в начале строки.
>>> None == re.match('\d{3}-\d{3}-\d{4}', '495-456-9102 Мой номер') False >>> None == re.match('\d{3}-\d{3}-\d{4}', 'Мой номер 495-456-9102') True
Метод re.compite()
позволяет собрать регулярное выражение в отдельный объект, который может быть использован для поиска. Это также избавляет от переписывания одного и того же выражения.
regexp = re.compile('\d{3}-\d{3}-\d{4}') match = regexp.search('Мой номер 495-456-9102') print('Найденный телефонный номер: ' + match.group())
Найденный телефонный номер: 495-456-9102
Флаги компиляции регулярных выражений
re.A
илиre.ASCII
re.DEBUG
re.I
илиre.IGNORECASE
re.L
илиre.LOCALE
re.M
илиre.MULTILINE
re.S
илиre.DOTALL
re.X
илиre.VERBOSE
Игнорирование регистра при поиске соответствий
>>> re.search('robocop', 'RoboCop is part man, part machine, all cop.', re.IGNORECASE).group() 'RoboCop'
Комбинации .*
соответствует все, за исключением символа новой строки. С помощью re.DOTALL
можно установить режим, при котором точке соответствует также символ новой строки.
>>> re.search('.*', 'First line.\nSecond line.\nThird line.').group() 'First line.' >>> re.search('.*', 'First line.\nSecond line.\nThird line.', re.DOTALL).group() 'First line.\nSecond line.\nThird line.'
Если нужно использовать несколько флагов компиляции:
>>> regexp = re.compile('foo', re.DOTALL | re.IGNORECASE)
Флаг компиляции re.VERBOSE
включает многословный режим, при котором пробелы и комментарии игнорируются.
# регулярное выражение для номера телефона phoneRegex = re.compile(''' (?:\(?(\d{3})\)?)? # код города (?:\s|-)? # разделитель (\d{3}) # первые три цифры (?:\s|-)? # разделитель (\d{2}) # еще две цифры (?:\s|-)? # разделитель (\d{2}) # еще две цифры (?:\s*доб[.а-я]*\s*(\d{2,5}))? # добавочный ''', re.VERBOSE) # регулярное выражение для адреса эл.почты emailRegex = re.compile(''' [a-z0-9._-]+ # имя пользователя @ # @ [a-z0-9.-]+ # первая часть домена \.[a-z]{2,6} # вторая часть домена ''', re.VERBOSE | re.IGNORECASE)