Регулярные выражения
Регулярное выражение (сокращенно regex [...]) — это последовательность символов, которая определяет шаблон поиска в тексте. [...] используется алгоритмами поиска строк для операций «найти» или «найти и заменить» в строках, или для проверки ввода.
- Импортируйте модуль regex с помощью
import re. - Создайте объект Regex с помощью функции
re.compile(). (Не забудьте использовать необработанную строку (raw string).) - Передайте строку, которую вы хотите искать, в метод
search()объекта Regex. Это возвращает объектMatch. - Вызовите метод
group()объекта Match, чтобы вернуть строку фактически сопоставленного текста.
Все функции regex в Python находятся в модуле re:
# Import re module for regular expression operations
import re
Символы Regex
| Символ | Соответствует |
|---|---|
? | ноль или одно из предыдущей группы. |
* | ноль или более из предыдущей группы. |
+ | один или более из предыдущей группы. |
{n} | ровно n из предыдущей группы. |
{n,} | n или более из предыдущей группы. |
{,m} | от 0 до m из предыдущей группы. |
{n,m} | не менее n и не более m предыдущей группы. |
{n,m}? или *? или +? | выполняет нежадный (non-greedy) поиск предыдущей группы. |
^spam | означает, что строка должна начинаться с spam. |
spam$ | означает, что строка должна заканчиваться на spam. |
. | любой символ, кроме символов новой строки. |
\d, \w, и \s | цифра, слово или пробельный символ соответственно. |
\D, \W, и \S | что угодно, кроме цифры, слова или пробела соответственно. |
[abc] | любой символ между скобками (например, a, b, ). |
[^abc] | любой символ, которого нет между скобками. |
Объекты сопоставления regex
# re.compile(): create regex pattern object (use raw string r'' to avoid escaping)
phone_num_regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # Pattern: 3 digits-3 digits-4 digits
mo = phone_num_regex.search('My number is 415-555-4242.') # Search for pattern
print(f'Phone number found: {mo.group()}') # group() returns matched text
Phone number found: 415-555-4242
Группировка с помощью скобок
# Parentheses create groups: group(1) returns first group, group(2) returns second
phone_num_regex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)') # Two groups in parentheses
mo = phone_num_regex.search('My number is 415-555-4242.')
mo.group(1) # Returns first group: '415'
'415'
mo.group(2)
'555-4242'
mo.group(0)
'415-555-4242'
mo.group()
'415-555-4242'
Войдите в систему, чтобы ответить на эту викторину и отслеживать свой прогресс обучения
group() return when called on a match object?Чтобы получить все группы сразу, используйте метод groups():
# groups(): returns tuple of all groups
mo.groups() # Returns ('415', '555-4242')
('415', '555-4242')
area_code, main_number = mo.groups()
print(area_code)
415
print(main_number)
555-4242
Несколько групп с оператором “ИЛИ” (Pipe)
Вы можете использовать символ | везде, где хотите сопоставить одно из нескольких выражений.
hero_regex = re.compile (r'Batman|Tina Fey')
mo1 = hero_regex.search('Batman and Tina Fey.')
mo1.group()
'Batman'
mo2 = hero_regex.search('Tina Fey and Batman.')
mo2.group()
'Tina Fey'
Вы также можете использовать оператор “ИЛИ” для сопоставления одного из нескольких шаблонов как части вашего regex:
bat_regex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = bat_regex.search('Batmobile lost a wheel')
mo.group()
'Batmobile'
mo.group(1)
'mobile'
Необязательное сопоставление с помощью знака вопроса
Символ ? помечает группу, предшествующую ему, как необязательную часть шаблона.
bat_regex = re.compile(r'Bat(wo)?man')
mo1 = bat_regex.search('The Adventures of Batman')
mo1.group()
'Batman'
mo2 = bat_regex.search('The Adventures of Batwoman')
mo2.group()
'Batwoman'
Сопоставление нуля или более с помощью Звездочки
* (звездочка или астериск) означает «сопоставить ноль или более». Группа, предшествующая звездочке, может встречаться в тексте любое количество раз.
bat_regex = re.compile(r'Bat(wo)*man')
mo1 = bat_regex.search('The Adventures of Batman')
mo1.group()
'Batman'
mo2 = bat_regex.search('The Adventures of Batwoman')
mo2.group()
'Batwoman'
mo3 = bat_regex.search('The Adventures of Batwowowowoman')
mo3.group()
'Batwowowowoman'
Сопоставление одного или более с помощью Плюса
+ (или плюс) означает сопоставить один или более. Группа, предшествующая плюсу, должна встречаться как минимум один раз:
bat_regex = re.compile(r'Bat(wo)+man')
mo1 = bat_regex.search('The Adventures of Batwoman')
mo1.group()
'Batwoman'
mo2 = bat_regex.search('The Adventures of Batwowowowoman')
mo2.group()
'Batwowowowoman'
mo3 = bat_regex.search('The Adventures of Batman')
mo3 is None
True
Сопоставление конкретных повторений с помощью фигурных скобок
Если у вас есть группа, которую вы хотите повторить определенное количество раз, следуйте за группой в вашем regex числом в фигурных скобках:
ha_regex = re.compile(r'(Ha){3}')
mo1 = ha_regex.search('HaHaHa')
mo1.group()
'HaHaHa'
mo2 = ha_regex.search('Ha')
mo2 is None
True
Вместо одного числа вы можете указать диапазон с минимумом и максимумом между фигурными скобками. Например, regex (Ha){3,5} сопоставит ‘HaHaHa’, ‘HaHaHaHa’ и ‘HaHaHaHaHa’.
ha_regex = re.compile(r'(Ha){2,3}')
mo1 = ha_regex.search('HaHaHaHa')
mo1.group()
'HaHaHa'
Жадное и нежадное сопоставление
Регулярные выражения Python по умолчанию являются жадными (greedy): в неоднозначных ситуациях они будут сопоставлять максимально длинную строку. Нежадная версия фигурных скобок, которая сопоставляет минимально возможную строку, имеет закрывающую фигурную скобку, за которой следует вопросительный знак.
greedy_ha_regex = re.compile(r'(Ha){3,5}')
mo1 = greedy_ha_regex.search('HaHaHaHaHa')
mo1.group()
'HaHaHaHaHa'
non_greedy_ha_regex = re.compile(r'(Ha){3,5}?')
mo2 = non_greedy_ha_regex.search('HaHaHaHaHa')
mo2.group()
'HaHaHa'
Войдите в систему, чтобы ответить на эту викторину и отслеживать свой прогресс обучения
_ instead of +? after the quantifier (e.g., _?, +?, {3,5}?)Метод findall()
Метод findall() вернет строки каждого совпадения в искомой строке.
phone_num_regex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # has no groups
phone_num_regex.findall('Cell: 415-555-9999 Work: 212-555-0000')
['415-555-9999', '212-555-0000']
Создание собственных классов символов
Вы можете определить свой собственный класс символов, используя квадратные скобки. Например, класс символов [aeiouAEIOU] будет соответствовать любой гласной, как строчной, так и заглавной.
vowel_regex = re.compile(r'[aeiouAEIOU]')
vowel_regex.findall('Robocop eats baby food. BABY FOOD.')
['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']
Вы также можете включать диапазоны букв или цифр, используя дефис. Например, класс символов [a-zA-Z0-9] будет соответствовать всем строчным буквам, заглавным буквам и цифрам.
Поместив символ каретки (^) сразу после открывающей скобки класса символов, вы можете создать отрицательный класс символов, который будет соответствовать всем символам, которых нет в классе символов:
consonant_regex = re.compile(r'[^aeiouAEIOU]')
consonant_regex.findall('Robocop eats baby food. BABY FOOD.')
['R', 'b', 'c', 'p', ' ', 't', 's', ' ', 'b', 'b', 'y', ' ', 'f', 'd', '.', ' ', 'B', 'B', 'Y', ' ', 'F', 'D', '.']
Символы Каретки и Знака доллара
Вы также можете использовать символ каретки
^в начале regex, чтобы указать, что совпадение должно произойти в начале искомого текста.Аналогично, вы можете поместить знак доллара
$в конец regex, чтобы указать, что строка должна заканчиваться этим шаблоном regex.И вы можете использовать
^и$вместе, чтобы указать, что вся строка должна соответствовать regex.
Строка регулярного выражения r'^Hello' соответствует строкам, начинающимся с ‘Hello’:
begins_with_hello = re.compile(r'^Hello')
begins_with_hello.search('Hello world!')
<_sre.SRE_Match object; span=(0, 5), match='Hello'>
begins_with_hello.search('He said hello.') is None
True
Строка регулярного выражения r'\d\$' соответствует строкам, которые заканчиваются числовым символом от 0 до 9:
whole_string_is_num = re.compile(r'^\d+$')
whole_string_is_num.search('1234567890')
<_sre.SRE_Match object; span=(0, 10), match='1234567890'>
whole_string_is_num.search('12345xyz67890') is None
True
whole_string_is_num.search('12 34567890') is None
True
Символ подстановки (Wildcard)
Символ . (или точка) в регулярном выражении соответствует любому символу, кроме символа новой строки:
at_regex = re.compile(r'.at')
at_regex.findall('The cat in the hat sat on the flat mat.')
['cat', 'hat', 'sat', 'lat', 'mat']
Сопоставление всего с помощью Dot-Star
name_regex = re.compile(r'First Name: (.*) Last Name: (.*)')
mo = name_regex.search('First Name: Al Last Name: Sweigart')
mo.group(1)
'Al'
mo.group(2)
'Sweigart'
.* использует жадный режим: он всегда будет пытаться сопоставить как можно больше текста. Чтобы сопоставить любой текст в нежадном режиме, используйте точку, звездочку и вопросительный знак (.*?). Вопросительный знак указывает Python сопоставлять нежадным образом:
non_greedy_regex = re.compile(r'<.*?>')
mo = non_greedy_regex.search('<To serve man> for dinner.>')
mo.group()
'<To serve man>'
greedy_regex = re.compile(r'<.*>')
mo = greedy_regex.search('<To serve man> for dinner.>')
mo.group()
'<To serve man> for dinner.>'
Сопоставление новых строк с помощью символа Dot
Dot-star сопоставляет все, кроме новой строки. Передавая re.DOTALL в качестве второго аргумента в re.compile(), вы можете заставить символ точки сопоставлять все символы, включая символ новой строки:
no_newline_regex = re.compile('.*')
no_newline_regex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
'Serve the public trust.'
newline_regex = re.compile('.*', re.DOTALL)
newline_regex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
'Serve the public trust.\nProtect the innocent.\nUphold the law.'
Регистронезависимое сопоставление
Чтобы сделать ваше regex регистронезависимым, вы можете передать re.IGNORECASE или re.I в качестве второго аргумента в re.compile():
robocop = re.compile(r'robocop', re.I)
robocop.search('Robocop is part man, part machine, all cop.').group()
'Robocop'
robocop.search('ROBOCOP protects the innocent.').group()
'ROBOCOP'
robocop.search('Al, why does your programming book talk about robocop so much?').group()
'robocop'
Замена строк с помощью метода sub()
Метод sub() для объектов Regex принимает два аргумента:
- Первый аргумент — это строка для замены любых совпадений.
- Второй — это строка для регулярного выражения.
Метод sub() возвращает строку с примененными заменами:
names_regex = re.compile(r'Agent \w+')
names_regex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.')
'CENSORED gave the secret documents to CENSORED.'
Войдите в систему, чтобы ответить на эту викторину и отслеживать свой прогресс обучения
sub() method do?Управление сложными Regex
Чтобы указать функции re.compile() игнорировать пробелы и комментарии внутри строки регулярного выражения, можно включить «подробный режим» (verbose mode), передав переменную re.VERBOSE в качестве второго аргумента в re.compile().
Теперь вместо трудночитаемого регулярного выражения, такого как это:
phone_regex = re.compile(r'((\d{3}|\(\d{3}\))?(\s|-|\.)?\d{3}(\s|-|\.)\d{4}(\s*(ext|x|ext.)\s*\d{2,5})?)')
вы можете разбить регулярное выражение на несколько строк с комментариями, как показано ниже:
phone_regex = re.compile(r'''(
(\d{3}|\(\d{3}\))? # area code
(\s|-|\.)? # separator
\d{3} # first 3 digits
(\s|-|\.) # separator
\d{4} # last 4 digits
(\s*(ext|x|ext.)\s*\d{2,5})? # extension
)''', re.VERBOSE)
Войдите в систему, чтобы ответить на эту викторину и отслеживать свой прогресс обучения
re.VERBOSE do when passed to re.compile()?