Урок 46 из 84 · ООП
Регулярные выражения
Содержание урока
Регулярное выражение — это строка, задающая шаблон поиска подстрок в тексте. Одному шаблону может соответствовать много разных строчек. Термин «Регулярные выражения» является переводом английского словосочетания «Regular expressions». Перевод не очень точно отражает смысл, правильнее было бы «шаблонные выражения». Регулярное выражение, или коротко «регулярка», состоит из обычных символов и специальных командных последовательностей. Например, \d задаёт любую цифру, а \d+ — задает любую последовательность из одной или более цифр. Работа с регулярками реализована во всех современных языках программирования. Однако существует несколько «диалектов», поэтому функционал регулярных выражений может различаться от языка к языку. В некоторых языках программирования регулярками пользоваться очень удобно (например, в питоне), в некоторых — не слишком (например, в C++).
Примеры регулярных выражений
| Title | Регулярка | Её смысл |
|---|---|---|
hello world |
В точности текст «simple text» | |
\d{5} |
Последовательности из 5 цифр\d означает любую цифру{5} — ровно 5 раз |
|
\d\d/\d\d/\d{4} |
Даты в формате ДД/ММ/ГГГГ(и прочие куски, на них похожие, например, 98/76/5432) | |
\b\w{3}\b |
Слова в точности из трёх букв\b означает границу слова(с одной стороны буква, а с другой — нет)\w — любая буква,{3} — ровно три раза |
|
[-+]?\d+ |
Целое число, например, 7, +17, -42, 0013 (возможны ведущие нули)[-+]? — либо -, либо +, либо пусто\d+ — последовательность из 1 или более цифр |
Основы синтаксиса
Любая строка (в которой нет символов .^$*+?{}[]\|())
сама по себе является регулярным выражением. Так, выражению Хаха
будет соответствовать строка “Хаха” и только она. Регулярные выражения являются регистрозависимыми, поэтому строка “хаха” (с маленькой буквы) уже не будет соответствовать выражению выше. Подобно строкам в языке Python, регулярные выражения имеют спецсимволы
.^$*+?{}[]\|()
которые в регулярках являются управляющими конструкциями. Для написания их просто как символов требуется их экранировать, для чего нужно поставить перед ними знак \
Так же, как и в питоне, в регулярных выражениях выражение \n соответствует концу строки, а \t — табуляции.
Шаблоны, соответствующие одному символу
| Title | Применяем к тексту | Описание | Шаблон | Пример |
|---|---|---|---|---|
| молоко, малако,Им0л0коИхлеб | Один любой символ, кроме новой строки \n. |
. |
м.л.ко |
|
| СУ35, СУ111, АЛСУ14 | Любая цифра | \d |
СУ\d\d |
|
| 926)123, 1926-1234 | Любой символ, кроме цифры | \D |
926\D123 |
|
| бор ода, бор ода, борода |
Любой пробельный символ (пробел, табуляция, конец строки и т.п.) | \s |
бор\sода |
|
| X123, я123, !123456, 1 + 123456 | Любой непробельный символ | \S |
\S123 |
|
| Год, f_3, qwert | Любая буква (то, что может быть частью слова), а также цифры и _ |
\w |
\w\w\w |
|
| сом!, сом? | Любая не-буква, не-цифра и не подчёркивание | \W |
сом\W |
|
| 12, 1F, 4B | Один из символов в скобках,а также любой символ из диапазона a-b |
[..] |
[0-9][0-9A-Fa-f] |
|
| <1>, <a>, <>> | Любой символ, кроме перечисленных | [^..] |
<[^>]> |
|
Буква “ё” не включается в общий диапазон букв!Вообще говоря, в \d включается всё, что в юникоде помечено как «цифра», а в \w — как буква. Ещё много всего! |
\d≈[0-9],\D≈[^0-9],\w≈[0-9a-zA-Zа-яА-ЯёЁ],\s≈[ \f\n\r\t\v] |
|||
| если нужен минус, его нужно указать последним или первым | [abc-], [-1] |
|||
внутри скобок нужно экранировать только ] и \ |
[*[(+\\\]\t] |
|||
| вал, перевал, Перевалка | Начало или конец слова (слева пусто или не-буква, справа буква и наоборот).В отличие от предыдущих соответствует позиции, а не символу | \b |
\bвал |
|
| перевал, вал, Перевалка | Не граница слова: либо и слева, и справа буквы,либо и слева, и справа НЕ буквы | \B |
\Bвал |
|
| перевал, вал, Перевалка | \Bвал\B |
Квантификаторы (указание количества повторений)
| Title | Пример | Применяем к тексту | Описание | Шаблон |
|---|---|---|---|---|
\d{4} |
1, 12, 123, 1234, 12345 | Ровно n повторений | {n} |
|
\d{2,4} |
1, 12, 123, 1234, 12345 | От m до n повторений включительно | {m,n} |
|
\d{3,} |
1, 12, 123, 1234, 12345 | Не менее m повторений | {m,} |
|
\d{,2} |
1, 12, 123 | Не более n повторений | {,n} |
|
валы? |
вал, валы, валов | Ноль или одно вхождение, синоним {0,1} |
? |
|
СУ\d* |
СУ, СУ1, СУ12, ... | Ноль или более, синоним {0,} |
* |
|
a\)+ |
a), a)), a))), ba)]) | Одно или более, синоним {1,} |
+ |
|
\(.*\)\(.*?\) |
(a + b) * (c + d) * (e + f)(a + b) * (c + d) * (e + f) | По умолчанию квантификаторы жадные —захватывают максимально возможное число символов.Добавление ? делает их ленивыми,они захватывают минимально возможное число символов |
*?+???{m,n}?{,n}?{m,}? |
Регулярки в питоне
Функции для работы с регулярками живут в модуле re. Основные функции:
| Title | Её смысл | Функция |
|---|---|---|
Найти в строке string первую строчку, подходящую под шаблон pattern; |
re.search(pattern, string) |
|
Проверить, подходит ли строка string под шаблон pattern; |
re.fullmatch(pattern, string) |
|
Аналог str.split(), только разделение происходит по подстрокам, подходящим под шаблон pattern; |
re.split(pattern, string, maxsplit=0) |
|
Найти в строке string все непересекающиеся шаблоны pattern; |
re.findall(pattern, string) |
|
Итератор всем непересекающимся шаблонам pattern в строке string (выдаются match-объекты); |
re.finditer(pattern, string) |
|
Заменить в строке string все непересекающиеся шаблоны pattern на repl; |
re.sub(pattern, repl, string, count=0) |
Пример использования всех основных функций
import re
match = re.search(r'\d\d\D\d\d', r'Телефон 123-12-12')
print(match[0] if match else 'Not found')
# -> 23-12
match = re.search(r'\d\d\D\d\d', r'Телефон 1231212')
print(match[0] if match else 'Not found')
# -> Not found
match = re.fullmatch(r'\d\d\D\d\d', r'12-12')
print('YES' if match else 'NO')
# -> YES
match = re.fullmatch(r'\d\d\D\d\d', r'Т. 12-12')
print('YES' if match else 'NO')
# -> NO
print(re.split(r'\W+', 'Где, скажите мне, мои очки??!'))
# -> ['Где', 'скажите', 'мне', 'мои', 'очки', '']
print(re.findall(r'\d\d\.\d\d\.\d{4}',
r'Эта строка написана 19.01.2018, а могла бы и 01.09.2017'))
# -> ['19.01.2018', '01.09.2017']
for m in re.finditer(r'\d\d\.\d\d\.\d{4}', r'Эта строка написана 19.01.2018, а могла бы и 01.09.2017'):
print('Дата', m[0], 'начинается с позиции', m.start())
# -> Дата 19.01.2018 начинается с позиции 20
# -> Дата 01.09.2017 начинается с позиции 45
print(re.sub(r'\d\d\.\d\d\.\d{4}',
r'DD.MM.YYYY',
r'Эта строка написана 19.01.2018, а могла бы и 01.09.2017'))
# -> Эта строка написана DD.MM.YYYY, а могла бы и DD.MM.YYYY
Документация и ссылки
- Оригинальная документация: https://docs.python.org/3/library/re.html;
- Очень подробный и обстоятельный материал: https://www.regular-expressions.info/;
- Разные сложные трюки и тонкости с примерами: http://www.rexegg.com/;
- Он-лайн отладка регулярок https://regex101.com (не забудьте поставить галочку Python в разделе FLAVOR слева);
- Он-лайн визуализация регулярок https://www.debuggex.com/ (не забудьте выбрать Python);
- Могущественный текстовый редактор Sublime text 3, в котором очень удобный поиск по регуляркам;