Регулярные выражения в 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.ASCIIre.DEBUGre.Iилиre.IGNORECASEre.Lилиre.LOCALEre.Mилиre.MULTILINEre.Sилиre.DOTALLre.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)