Регулярные выражения
неплохая методичка, в которой есть практически всё про РВ, о чём говорилось в лекции. Серьёзно, прямо план лекции.
TODO трюк с составлением нечитаемого РВ из читаемых частей.
Копия плана (примеры и пояснения см. на сайте):
Что такое регулярные выражения?
- Спецсимволы
- Точка
- Набор символов (диапазон)
- Отрицание набора символов
- Повторения
- Звёздочка
- Плюс
- Знак вопроса
- Фигурные скобки
- Скобочные группы (карманы)
- Альтернация
- Экранирование
- Позиционные маркеры
- Каретка
- Доллар
- Дополнительные диапазоны и позиционные маркеры
- Контекстные проверки
- Предпросмотр, негативный предпросмотр
- Пост-просмотр, негативный пост-просмотр
- Флаги
- Поиск без учета регистра
- Многостроковый поиск
Перевод строки как любой символ
Ленивые повторители:
*?, +?, ??, {m, n}?
Опасность ленивых операций: «самый левый самый длинный» на атомарном уровне не работает; вложенные *? — путь в бесконечность
Алчные повторители:
*+, ++, ?+ и {m,n}+
(?>…) — общая конструкция алчной группировки
- Алчные повторители ускоряют разбор и (иногда) упрощают выражение
Особенности Python
Работа функций match() и search()
Результат — последовательность Match Object-ов
Именованные карманы (?P<name>…)
- Удобные инструменты:
split(), особенно с разделителями в карманах
Поиск с заменой
Самоцитаты (back references) — \номер скобочной группы (номер открывающей скобки в целом RE)
Пример: (\w+).*(\1) на текст Matches between zero and unlimited times, as match times
Именованные самоцитаты: (?P<name>…) ⇒ (?P=name)
Условные (
) самоцитаты: (?(id/name)yes-pattern|no-pattern)
В методичке нет про поиск с заменой sub()
Использование цитат в sub():
sub(r"(\w+).(\w+)", r"\2 — \1 — \1", "---qwerty---")
Ещё почитать
Д/З
- Прочитать и прощёлкать
методичку по regexp-ам
В частности, Match Objects
EJudge: XXL 'Размер имеет значение'
Input:Написать программу, которая в первой строке вводит два числа, оба в диапазоне от 2 до до 9 включительно. Эти числа определяют максимальное допустимое количество «X» в маркировке размера товара (соответственно, размера S и размера L), по аналогии с международной маркировкой (… XS, S, M, L, XL, XXL, …). Затем построчно вводится текст, содержащий такие маркировки. Программа выводит количество упоминаний каждого обозначения (в алфавитном порядке) в формате маркировка:количество. Если букв X в сокращении больше одной, допустимо писать число (2XS, 4XL и т. п.). Если сокращение не встретилось, оно не выводится. Сокращения ограничены не-буквами/не-цифрами, то есть DXXL или XXXXXXXXXXXS не является допустимым вариантом, а -XXL- — является. Ввод заканчивается пустой строкой.
Output:3,4 XXLXXL XXXXS L 02XS M XM SS.S.XXXD 3XL XXXL 2XS
L:1 M:1 S:1 XXS:1 XXXL:2
EJudge: IPv6Match 'Проверка IPv6'
Input:Написать функцию ipv6match(строка), которая проверяет, является ли некоторая строка синтаксически допустимым адресом IPv6 без использования номера порта и/или привязки к сетевому интерфейсу и без учёта рекомендаций по устранению неоднозначности. Дополнительные требования:
- сопоставление должно производиться по одному регулярному выражению
каждый самостоятельно значимый компонент этого выражения должен быть описан отдельно. Например, если бы потребовалось проверить целочисленную дробь, вместо «fr = r"-?[1-9]\d*/-?[1-9]\d*"» следовало бы писать
Функция должна возвращать результат работы re.match().
Output:1 tst = """2001:db8:0:0:1:0:0:1 2 2001:db8:bad:0:0:1:0:0:1 3 2001:0db8:0:0:1:0:0:1 4 2001:db8::1:0:0:1 5 2001:db8::0:1:0::0 6 2001:00db8::1:0:0:1 7 2001:DB8:0:0:1::1 8 2001:db8:0000:0:1::1 9 2001:Db8:0:0:0xff:1:: 10 ::1 11 :: 12 2:: 13 2:2::""" 14 for s in tst.split("\n"): 15 if res := ipv6match(s): 16 print(res.group()) 17 else: 18 print("NO")
2001:db8:0:0:1:0:0:1 NO 2001:0db8:0:0:1:0:0:1 2001:db8::1:0:0:1 NO NO 2001:DB8:0:0:1::1 2001:db8:0000:0:1::1 NO ::1 :: 2:: 2:2::
EJudge: GuitarChords 'Гитарные аккорды'
Input:Сильно упрощённое задание гитарного аккорда выглядит так:
- Сначала идёт буква ноты (A-G),
затем — необязательный знак бемоля b (нет у нот C и F) или диеза # (нет у нот B и E),
- Затем — необязательный модификатор аккорда "m", "7", "Sus2", "SUS4", "7", "m7", "maj7", "M9", или "m9".
Кроме того, аккорд может сопровождаться табулатурой вида Аккорд: [шесть_номеров_ладов], где номер лада — это либо цифра, либо двузначное число в скобках (от 10 до 14 включительно); вместо номера лада может стоять "X" или "x" — это означает, что соответствующая струна не используется. Строй гитары считается классическим: E A D G B E.
- Написать программу, которая вводит строку и с помощью регулярных выражений выделяет из неё все задания аккордов, а если при аккорде указана табулатура — проверяет, есть ли в табулатуре тоника (взятая на какой-либо струне нота, по имени которой назван аккорд). На 12 ладу название ноты совпадает с открытой струной, на 13 и 14 — соответственно с 1 и вторым ладом.
Программа должна выводить тоники аккордов и добавлять «!», если табулатура указана, а тоники в неё нет.
Output:C#M9: [XX(11)898] BAm CSus2: [x35533] G#maj7 A: [002220] Cbm9 Am9BbM9A#A: [11111] EM9: [099800] C: [000000]
C#M9 B Am CSus2 G#maj7 A C Am9 BbM9 A# A EM9 C!
EJudge: PolyDot 'Точка в многоугольнике'
Input:Написать функцию info(dots, dot), которой передаются два параметра — последовательность точек dots и ещё одна точка dot. Точка — это кортеж или список из двух вещественных чисел, последовательность dots может быть итератором. В dots лежат координаты вершин (возможно, невыпуклого) многоугольника без самопересечений (это проверять не надо). Функция должна возвращать три значения: периметр многоугольника, информацию о том, выпуклый ли он, и принадлежит ли точка многоугольнику.
Output:1 tri = (0, 0), (0, 4), (3, 0) 2 dot, dot2, odot, odot2 = (1, 1), (1, 2), (2, 1), (-1, -1) 3 print("{:.2f} {} {}".format(*info(tri, dot))) 4 print("{:.2f} {} {}".format(*info(tri, odot))) 5 print("{:.2f} {} {}".format(*iter(info(tri + (odot,), dot2)))) 6 print("{:.2f} {} {}".format(*info(tri + (odot,), odot2)))
12.00 True True 12.00 True True 12.65 False True 12.65 False False
Генератор текстовых многоугольников и точки: ../07_Iterators/PolyTk.py
