Share This
Связаться со мной
Крути в низ
Categories
//Регулярные выражения Python

Регулярные выражения Python

Рассмотрим встроенные функции модуля re, научимся компилировать Regex-выражения и узнаем, как делать опережающие и ретроспективные проверки – позитивные и негативные. В конце статьи, как всегда, – 10 интересных заданий с решениями.

reguljarnye vyrazhenija python 0cd254c - Регулярные выражения Python

← Часть 15 Методы работы с файлами и файловой системой

Регулярные выражения (Regex) – это особые шаблоны для поиска определенных подстрок в текстовых документах и на веб-страницах. Концепция Regex появилась в 1951 году, стала популярной к 1968 году, и с тех пор в той или иной степени поддерживается в большинстве языков программирования общего назначения. Регулярные выражения используются в текстовых редакторах, в файловых менеджерах ОС, в OCR-приложениях для распознавания текста, в онлайн-поисковиках и браузерах. Кроме того, они применяются для:

  • валидации данных;
  • лексического анализа;
  • определения директив конфигурации и преобразования URL (Apache http.conf, mod_rewrite);
  • составления сложных SQL-запросов;
  • создания кастомных шаблонов URL-диспетчера (re_path() Django).

Регулярные выражения в Python

Для работы с Regex в Python используют встроенный модуль re, в который входят:

  • Набор функций для поиска и замены подстрок – ниже мы подробно рассмотрим примеры использования основных методов.
  • Компилятор re.compile – он создает Regex-объекты для повторного использования и ускоряет работу регулярных выражений, как мы увидим чуть позже.

Регулярные выражения состоят из литералов (букв и цифр) и метасимволов. Для экранирования спецсимволов применяют обратные слэши , или же заключают выражение в r-строку . Такой шаблон, к примеру, можно использовать для валидации email-адреса:

         r'^[a-zA-Z0-9._-]+@[a-zA-Z-.]+$'     

Этот шаблон – один из простейших, Regex-выражения для проверки email-адресов могут выглядеть гораздо сложнее. Для разработки и тестирования сложных Regex шаблонов используют специальные сервисы, например, Regex101:

reguljarnye vyrazhenija python 0fc0f48 - Регулярные выражения Python

regex101 – популярный онлайн конструктор Regex-шаблонов

Основные Regex методы в Python

re.match() – проверяет, начинается ли строка с нужного фрагмента:

         import re lst = ['abrakadabra', 'https://kadabra.com', 'https://proglib.io/p/weekly-23-novosti-podkasty-otbornye-stati-i-obuchayushchie-materialy-po-frontendu-2023-02-14 - статья по этой ссылке',        'http//:mysite.ru', 'www.abra.com', 'http//abra.com', 'https://abra.com/', 'это мой сайт - https://abrakadabra.com/',        'https://ru.wikipedia.org/wiki/%D0%9B%D1%8F%D0%B3%D1%83%D1%88%D0%BA%D0%B0-%D0%B3%D0%BE%D0%BB%D0%B8%D0%B0%D1%84'] url = r'https?://(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}b([-a-zA-Z0-9()!@:%_+.~#?&/=]*)' for i in lst:     m = re.match(url, i)     if m:         print(m.group(0)) # валидная ссылка извлекается из начала строки       

Вывод:

         https://kadabra.com https://proglib.io/p/weekly-23-novosti-podkasty-otbornye-stati-i-obuchayushchie-materialy-po-frontendu-2023-02-14 https://abra.com/ https://ru.wikipedia.org/wiki/%D0%9B%D1%8F%D0%B3%D1%83%D1%88%D0%BA%D0%B0-%D0%B3%D0%BE%D0%BB%D0%B8%D0%B0%D1%84     

Если нужный фрагмент содержится в тексте, но не в начале строки – re.match() вернет None:

         >>> import re >>> s = 'ой, мороз, мороз, не морозь меня' >>> print(re.match('мороз', s)) None      

Метод re.fullmatch() возвращает совпадение, если вся строка полностью соответствует шаблону:

         >>> st1, st2 = 'одна строка', 'строка' >>> print(re.fullmatch(r'строка', st1)) None >>> print(re.fullmatch(r'строка', st2)) <re.Match object; span=(0, 6), match='строка'>      

Чтобы найти первое вхождение подстроки в текст, используют re.search(), при необходимости – с флагом re.I для игнорирования регистра:

         >>> s = 'Синий, синий иней лег на провода' >>> print(re.search('синий', s, re.I)) <re.Match object; span=(0, 5), match='Синий'>      

Метод re.search() можно использовать с дополнительными параметрами span(), string и group().

span возвращает начальный и конечный индексы вхождения:

         >>> text = 'Однажды весною, в час небывало жаркого заката, в Москве, на Патриарших прудах, появились два гражданина.' >>> print(re.search('пруд', text).span())   (71, 75)      

string возвращает строку, содержащую искомый фрагмент:

         >>> st = 'Дракула Брэма Стокера' >>> print(re.search('Сток', st).string)  Дракула Брэма Стокера      

group вернет подстроку, совпадающую с запросом:

         >>> st = 'пример домашнего хищника: кот'  >>> print(' текст найден - ', re.search(r'хищника:swww', st).group()) текст найден - хищника: кот      

Все вхождения фрагмента можно найти с помощью re.findall():

         >>> st = 'Eins Hier kommt die Sonne, Zwei Hier kommt die Sonne' >>> print(re.findall('Hier kommt die Sonne', st)) ['Hier kommt die Sonne', 'Hier kommt die Sonne']      

Метод re.split() разделяет строку по заданному шаблону:

         >>> st = 'мороз и солнце, день чудесный' >>> print(re.split(r'sиs', st, 1)) ['мороз', 'солнце, день чудесный']      

Для замены символов и подстрок используют re.sub(). В этом примере регулярное выражение предусматривает удаление из текста всех символов, кроме букв, цифр, знака перевода на новую строку, точки, пробела, вопросительного знака и запятой:

         >>> st = 'П#$%^рив&*ет, ка@!к успе~@хи с Py$%^*&thon?' >>> print(re.sub('[^а-яА-Яa-zA-Z0-9,? n.]', '', st)) Привет, как успехи с Python?      

Скорость работы скомпилированных Regex-выражений

Компилятор re.compile() применяют в тех случаях, когда шаблон выражения используется повторно:

         import re url_lst = ['https://mysite.ru/uploads/2023/2/1/image.jpg',            'https://mysite.ru/uploads/2023/2/1/image.html',            'http://www.mysite.ru/uploads/2022/2/1/another_image.png',            'http://mysite.ru/uploads/2022/12/15/images.doc',            'https://www.mysite.ru/uploads/2022/12/11/image22.jpg',            'http://mysite.ru/images/2023/2/5/gifimage.gif',            'https://mysite.ru/texts/2023/2/1/novel.txt',            'https://mysite.ru/books/2023/2/1/book.epub'] img_url = re.compile(r'https?://(www)?.*.(png|jpg|gif)') for url in url_lst:     if img_url.match(url):         print(url)      

Вывод:

         https://mysite.ru/uploads/2023/2/1/image.jpg http://www.mysite.ru/uploads/2022/2/1/another_image.png https://www.mysite.ru/uploads/2022/12/11/image22.jpg http://mysite.ru/images/2023/2/5/gifimage.gif     

Как уже упоминалось выше, скомпилированные выражения удобны не только потому, что их можно использовать многократно – они, к тому же, быстрее работают. Чем сложнее выражение и чем больше объем обрабатываемых данных – тем очевиднее преимущество. Проверим, насколько отличается скорость работы обычного регулярного выражения от скомпилированного – возьмем объемный файл («Преступление и наказание» Ф. М. Достоевского) и проведем поиск всех строк, в которых одновременно содержатся имя «Родион» и фамилия «Раскольников» в любых возможных склонениях, при этом между именем и фамилией должно быть не более 5 других слов:

         import re import time  start = time.time() with open('prestuplenie-i-nakazanie.txt', 'r', encoding='utf8') as book:     result = [line for line in book if re.findall(r'bРодиоw{0,3}(?:s+S+){0,5}s+Раскольникоw{0,3}b', line)] print(f'Найдено {len(result)} совпадений. Поиск без компиляции занял {time.time() - start:.2f} секунд')  start = time.time() with open('prestuplenie-i-nakazanie.txt', 'r', encoding='utf8') as book:     find_name = re.compile(r'bРодиоw{0,3}(?:s+S+){0,5}s+Раскольникоw{0,3}b')     result2 = [line for line in book if find_name.findall(line)] print(f'Найдено {len(result2)} совпадений. Поиск с компиляцией занял {time.time() - start:.2f} секунд')      

Результат:

         Найдено 5 совпадений. Поиск без компиляции занял 0.11 секунд Найдено 5 совпадений. Поиск с компиляцией занял 0.07 секунд      

Конструирование регулярных выражений в Python

Regex-шаблоны в Python, как уже упоминалось выше, состоят из метасимволов и литералов, которые определяют символьные комбинации – последовательности, наборы и диапазоны. Регулярные выражения ищут совпадения в обрабатываемом тексте в соответствии с этими комбинациями.

Метасимволы

Рассмотрим основные метасимволы, которые используются для составления Regex-шаблонов.

[] – определяет набор (или диапазон) символов:

         >>> st = 'Роман "Война и мир", автор - Лев Николаевич Толстой' >>> re.findall(r'[о-с]', st, re.I) ['Р', 'о', 'о', 'р', 'о', 'р', 'о', 'о', 'с', 'о'] >>> re.findall(r'[абвлнт]', st, re.I) ['а', 'н', 'В', 'н', 'а', 'а', 'в', 'т', 'Л', 'в', 'Н', 'л', 'а', 'в', 'Т', 'л', 'т']      

– задает начало последовательности, а также экранирует служебные символы:

         >>> st = 'www.google.com, www.yandex.ru' >>> re.findall(r'.comb', st) ['.com']      

. – позволяет выбрать любой символ, кроме n:

         >>> st = 'Pythonn' >>> re.findall(r'.', st) ['P', 'y', 't', 'h', 'o', 'n']      

^ – определяет, начинается ли строка с определенного символа (слова, набора слов или символов). При совместном использовании с [], напротив, игнорирует набор заданных символов:

         >>> st = 'Регулярные выражения в Python' >>> re.match(r'^Р', st) <re.Match object; span=(0, 1), match='Р'> >>> re.findall(r'регулярные^[pyt]', st, re.I) []      

$ – определяет, заканчивается ли строка нужным словом, символов или набором символов:

         >>> st1, st2 = 'JavaScript', 'Python' >>> print(re.search('pt$', st2)) None >>> re.search('pt$', st1) <re.Match object; span=(8, 10), match='pt'>      

. – соответствует 0 или более символов:

         >>> st = 'кооперация, координация, коллаборация' >>> re.findall(r'коо.*', st) ['кооперация, координация, коллаборация']      

+ – соответствует 1 и более символов:

         >>> st = 'лаборант' >>> re.findall(r'лоб.+', st) [] >>> st = 'лоббирование' >>> re.findall(r'лоб.+', st) ['лоббирование']      

? – обнаруживает наличие 0 или 1 совпадения с шаблоном, а также нейтрализует «жадные» выражения с метасимволами ., *, и +:

         >>> st = 'инновационный' >>> re.findall(r'.?нн', st) ['инн', 'онн']      

{} – ищет точное число совпадений, которое указывается в скобках:

         >>> st = 'паллиативный, плеоназм, баллистическая, конгрегация, аллопеция' >>> re.findall(r'л{2}', st) ['лл', 'лл', 'лл']      

| – обнаруживает совпадение с любым из указанных вариантов:

         >>> st = 'есть карандаши двух цветов - красные и синие' >>> re.findall(r'красные|синие', st) ['красные', 'синие']      

() – выделяет группу символов:

         >>> st = 'адреса наших сайтов - www.site1.ru, www.site2.com, www.site3.io' >>> print(re.sub(r'(www.)', r'https://', st)) адреса наших сайтов - https://site1.ru, https://site2.com, https://site3.io      

<> – используется для работы с именованными группами:

         >>> info = 'января 12, 2002' >>> pattern = r'^(?P<месяц>w+)s(?P<день>d+),?s(?P<год>d+)' >>> matches = re.search(pattern, info) >>> print(f"Писатель родился в {matches.group('год')} году, {matches.group('день')} {matches.group('месяц')}") Писатель родился в 2002 году, 12 января      

Последовательности

Как уже упоминалось выше, знак обозначает определенную последовательность символов.

A – проверяет, начинается ли строка с заданной последовательности символов или слов:

         >>> text = 'О бойся Бармаглота, сын! Он так свирлеп и дик, А в глуще рымит исполин – Злопастный Брандашмыг.' >>> re.match(r'AО бойся', text) <re.Match object; span=(0, 7), match='О бойся'>      

b – проверяет, 1) начинается ли 2) заканчивается ли слово специфической последовательностью символов:

         >>> info = 'www.mysite.com, www.yoursite.com, www.oursite.io' >>> re.findall(r'(www.)b', info) ['www.', 'www.', 'www.'] >>> re.findall(r'(.io)b', info) ['.io']      

B – возвращает совпадение, если указанные символы присутствуют в строке, но 1) не в начале 2) не в конце слов:

         >>> st = 'красный, зеленый, нытик' >>> re.findall(r'Bны', st) ['ны', 'ны'] >>> re.findall(r'йB', st) []      

d – определяет, есть ли в строке цифры от 0 до 9:

         >>> st = 'собеседование назначено на 12 мая' >>> re.findall(r'd', st) ['1', '2']      

D – соответствует всем символам, кроме цифр:

         >>> st = '!#!@#@$%^номер начинается с +7' >>> re.findall(r'D', st) ['!', '#', '!', '@', '#', '@', '$', '%', '^', 'н', 'о', 'м', 'е', 'р', ' ', 'н', 'а', 'ч', 'и', 'н', 'а', 'е', 'т', 'с', 'я', ' ', 'с', ' ', '+']      

s – соответствует одному пробелу:

         >>> st = 'один пробел' >>> re.search(r's', st) <re.Match object; span=(4, 5), match=' '>      

S – напротив, соответствует любому символу, кроме пробела:

         >>> st = '   ' >>> re.findall(r'S', st) []      

w – соответствует любой букве, цифре или символу _:

         >>> st1, st2 = '!@$^^$%&*()@', 's5tf7_' >>> re.findall(r'w', st1) [] >>> re.findall(r'w', st2) ['s', '5', 't', 'f', '7', '_']      

W – совпадает с любым специальным символом, игнорирует буквы, цифры и _:

         >>> st1, st2 = '!@~#$%^&*(', 'a28df_r4ghgh' >>> re.findall(r'W', st1) ['!', '@', '~', '#', '$', '%', '^', '&', '*', '('] >>> re.findall(r'W', st2) []      

Z – проверяет, заканчивается ли строка нужной последовательностью:

         >>> st1, st2 = 'самый популярный язык - Python', 'главный язык интернета - JavaScript' >>> re.search(r'ScriptZ', st2) <re.Match object; span=(29, 35), match='Script'> >>> print(re.search(r'JavaZ', st1)) None      

Наборы и диапазоны символов

При составлении регулярных выражений диапазоны и наборы символов заключают в скобки []. Рассмотрим примеры таких шаблонов.

[абвгд], [1234], [!@%^] – находит совпадения с указанными буквами (цифрами, спецсимволами) в строке:

         >>> st1, st2 = 'строка без чисел', 'строка с ч1и2с3л4а5м6и' >>> re.findall(r'[сбч]', st1) ['с', 'б', 'ч', 'с'] >>> re.findall(r'[6789]')  ['6'] >>> re.findall(r'[!@#$%^]', 'abrakadabr@') ['@']      

[а-е], [а-еА-Е], [5-7] – находят совпадения с буквами и цифрами из указанных диапазонов:

         >>> st1, st2 = 'Мурзилка - советский журнал для детей', 'любимая цифра - 5' >>> re.findall(r'[дежз]', st1) ['з', 'е', 'ж', 'д', 'д', 'е', 'е'] >>> re.findall(r'[м-оМО]', st1) ['М', 'о', 'н'] >>> re.findall(r'[4-7]', st2) ['5']      

[^абв], [^123], [^!@#$] – совпадает с любым символом, не входящим в указанный набор (диапазон):

         >>> st = 'пример строки с ц1и2ф3рами и с!мвол@ми' >>> re.findall(r'[^3-5]', st) ['п', 'р', 'и', 'м', 'е', 'р', ' ', 'с', 'т', 'р', 'о', 'к', 'и', ' ', 'с', ' ', 'ц', '1', 'и', '2', 'ф', 'р', 'а', 'м', 'и', ' ', 'и', ' ', 'с', '!', 'м', 'в', 'о', 'л', '@', 'м', 'и'] >>> re.findall(r'[^а-о]', st) ['п', 'р', 'р', ' ', 'с', 'т', 'р', ' ', 'с', ' ', 'ц', '1', '2', 'ф', '3', 'р', ' ', ' ', 'с', '!', '@'] >>> re.findall(r'[^#$%^&*()_+]', st) ['п', 'р', 'и', 'м', 'е', 'р', ' ', 'с', 'т', 'р', 'о', 'к', 'и', ' ', 'с', ' ', 'ц', '1', 'и', '2', 'ф', '3', 'р', 'а', 'м', 'и', ' ', 'и', ' ', 'с', '!', 'м', 'в', 'о', 'л', '@', 'м', 'и']      

[0-9][0-9] – позволяет задавать совпадения по двузначным цифрам:

         >>> st = 'встреча назначена на 10:45' >>> re.findall(r'[0-9][0-9]', st) ['10', '45']      

Флаги в регулярных выражениях

В Python предусмотрены дополнительные параметры для Regex-шаблонов – флаги, причем использовать можно и полную, и краткую форму параметра. Ранее мы уже встречались с флагом re.I – это краткий вариант re.IGNORECASE. На практике флаг re.I используется чаще всего, но остальные флаги тоже могут пригодиться.

re.I, re.IGNORECASE – игнорирует регистр:

         >>> st = 'Яблоко от яблони недалеко падает' >>> re.findall('ябл', st, re.I) ['Ябл', 'ябл']      

re.A, re.ASCII – находит ASCII-символы, игнорируя все остальные:

         st = 'одно из слов для обозначения дракона в японском - ドラゴン, doragon' >>> re.findall(r'w+', st, re.A) ['doragon']      

re.M, re.MULTILINE – находит совпадения в начале ^ и конце $ каждой строки в многострочном фрагменте текста:

         >>> st = 'Это пример текста,n состоящего изn нескольких строкn' >>> print(re.search(r'^sсостоящего', st)) None >>> print(re.search(r'^sсостоящего', st, re.M)) <re.Match object; span=(19, 30), match=' состоящего'>      

re.S, re.DOTALL – позволяет метасимволу . возвращать совпадения по всем символам, включая n:

         >>> st = 'примерn строкиn nс nсимволом "n"' >>> re.findall('.', st) ['п', 'р', 'и', 'м', 'е', 'р', ' ', 'с', 'т', 'р', 'о', 'к', 'и', ' ', 'с', ' ', 'с', 'и', 'м', 'в', 'о', 'л', 'о', 'м', ' ', '"', '"'] >>> re.findall('.', st, re.S) ['п', 'р', 'и', 'м', 'е', 'р', 'n', ' ', 'с', 'т', 'р', 'о', 'к', 'и', 'n', ' ', 'n', 'с', ' ', 'n', 'с', 'и', 'м', 'в', 'о', 'л', 'о', 'м', ' ', '"', 'n', '"']      

re.X, re.VERBOSE – позволяет использовать комментарии в Regex-шаблонах:

         import re pattern = re.compile(r'''                      ^[a-zA-Z0-9._-]+ # первая часть адреса содержит буквы, цифры, подчеркивание и дефис                      @ # первая часть адреса соединяется со второй символом @                      [a-zA-Z.-]+$ # заключительная часть - доменное имя (может содержать дефис) и доменная зона                      ''', re.X) emails = ['python4ik@python.org', '@4##@%@mail.ru',           'python@yandex.ru', 'my_em@il@mail.com']  for email in emails:     if pattern.fullmatch(email):         print(email)      

Вывод:

         python4ik@python.org python@yandex.ru      

Опережающие и ретроспективные проверки

Как и большинство других современных языков программирования, Python поддерживает опережающие и ретроспективные проверки – позитивные и негативные.

Позитивная опережающая проверка:

X(?=Y) – вернуть X только в том случае, если выполняется Y.

Негативная опережающая проверка:

X(?!Y) – вернуть X только в том случае, если не выполняется Y.

Ретроспективная позитивная проверка:

(?<=Y)X – вернуть X при условии, что перед ним есть Y.

Ретроспективная негативная проверка:

(?<!Y)X – вернуть совпадение с X при условии, что перед ним нет Y.

Вот пример позитивной опережающей проверки – здесь Regex-шаблон находит в тексте слова, которые 1) имеют длину ровно 10 символов; 2) включают в себя подстроку «кофе»:

         import re pattern = re.compile(r'(?=bw{10}b)w*?кофеw*', re.I) text = '''В кофейне появились новые кофемашина и кофемолка. Кофемашина делает все виды  кофеиносодержащих  и некофейных напитков (чай и какао).''' print(pattern.findall(text))     

Вывод:

         ['кофемашина', 'Кофемашина', 'некофейных']     

А это пример негативной опережающей проверки – шаблон находит совпадения только по тем цифрам, после которых нет «руб»:

         >>> import re >>> st = '1 месяц хостинга стоит 200 руб' >>> re.findall(r'd+(?!sруб)b', st) ['1']      

Ретроспективная позитивная проверка здесь находит числа, перед которыми стоит «рублей»:

         >>> st = 'VPN на 2 месяца стоит рублей 300' >>> re.findall(r'(?<=рублейs)d+', st) ['300']      

А здесь ретроспективная негативная проверка находит числа, перед которыми нет «примерно»:

         >>> st = 'Стоимость 2 приличных ноутбуков - примерно 4 тысячи долларов' >>> re.findall(r'(?<!примерноs)d+', st) ['2']      

Практика

Задание 1

Напишите регулярное выражения, которое находит в полученной от пользователя строке все слова с дефисом.

Пример ввода:

         Почему-то часто никак как-то получилось что-то зачем-то опять Кто-то     

Вывод:

         ['Почему-то', 'как-то', 'что-то', 'зачем-то', 'Кто-то']     

Решение с Regex:

         import re st = input() print(re.findall(r'b[а-я]+-[а-я]+b', st, re.I))        

Решение без Regex:

         st = input().lower().split() print([i for i in st if '-' in i])     

Задание 2

Напишите программу, которая с помощью Regex-шаблона определяет, сколько слов в полученной от пользователя строке начинаются с «ко» или «коо».

Пример ввода:

         Книга компьютер крот Колобок колхоз кооперация ноутбук карандаш координатор     

Вывод:

         5     

Решение с Regex:

         import re st = input() print(len(re.findall(r'ко{1,2}', st, re.I)))      

Решение без Regex:

         st = input().lower().split() print(len([i for i in st if i.startswith('ко') or i.startswith('коо')]))      

Задание 3

Напишите регулярное выражение, которое удаляет из текста все знаки препинания, кроме дефиса.

Пример ввода:

         "Это" - фрагмент текста, для обработки?!..      

Вывод:

         Это - фрагмент текста для обработки     

Решение с Regex:

         import re st = input() print(re.sub(r'[,.?!:;"]', '', st))      

Решение без Regex:

         st = input() print(''.join([i for i in st if i.isalpha() or i == ' ' or i == '-']))      

Задание 4

Напишите регулярное выражение, которое находит в полученной от пользователя строке все слова, содержащие подстроку «круж», но не в начале и не в конце слова.

Пример ввода:

         окружность кружево кружка окружение головокружение кружок кружкруж     

Вывод:

         окружность окружение головокружение      

Решение с Regex:

         import re st = input().split() for i in st:     if re.search(r'BкружB', i):         print(i)      

Решение без Regex:

         st = input().split() for i in st:     if 'круж' in i:         if i.startswith('круж'):             continue         elif i.endswith('круж'):             continue         else:             print(i)      

Задание 5

Напишите регулярное выражение, которое меняет формат даты в URL с ГГГГ/ММ/ДД на ДД/ММ/ГГГГ.

Пример ввода:

         https://www.washingtonpost.com/technology/2023/02/14/what-is-temu-super-bowl-commercial/     

Вывод:

         https://www.washingtonpost.com/technology/14/02/2023/what-is-temu-super-bowl-commercial/     

Решение:

         import re url = input() print(re.sub(r'(d{4})/(d{1,2})/(d{1,2})', r'3/2/1', url))      

Задание 6

Напишите программу, которая:

  • Получает от пользователя n строк с данными студентов.
  • Извлекает имена, фамилии и оценки по предметам без использования методов строк и словарей.
  • Создает и выводит список словарей.

Пример ввода:

         5 Денис,Ефремов,5,5,3,4 Юлия,Демидова,5,3,4,5 Евгения,Артемова,4,4,4,5 Сергей,Егоров,4,4,4,3 Кирилл,Антонов,4,5,3,3      

Вывод:

         [{'имя': 'Денис', 'фамилия': 'Ефремов', 'математика': '5', 'физика': '5', 'химия': '3', 'биология': '4'}, {'имя': 'Юлия', 'фамилия': 'Демидова', 'математика': '5', 'физика': '3', 'химия': '4', 'биология': '5'}, {'имя': 'Евгения', 'фамилия': 'Артемова', 'математика': '4', 'физика': '4', 'химия': '4', 'биология': '5'}, {'имя': 'Сергей', 'фамилия': 'Егоров', 'математика': '4', 'физика': '4', 'химия': '4', 'биология': '3'}, {'имя': 'Кирилл', 'фамилия': 'Антонов', 'математика': '4', 'физика': '5', 'химия': '3', 'биология': '3'}]     

Решение:

         import re pattern = re.compile(r'''(?P<имя>[^,]+), # именованная группа 1                          (?P<фамилия>[^,]+),  # именованная группа 2 и так далее                          (?P<математика>[^,]+),                          (?P<физика>[^,]+),                          (?P<химия>[^,]+),                          (?P<биология>[^,]+)                          ''', re.X) grades = [] for i in range(int(input())):     line = input()     grades.append(pattern.search(line).groupdict()) print(grades)     

Задание 7

Напишите регулярные выражения, которые:

  1. Заменяют все вхождения слова «красный» на «зеленый», но только в том случае, если перед словом «красный» нет союза «и».
  2. Находят все слова, которые не заканчиваются на «и» или «ый».
  3. Находят все слова, которые не начинаются с букв «к», «ф», «о» и имеют длину 2 и более символов.

Пример текста:

         st = '''красноватый фиолетовый и красный  красный и желтый красный желтый и красный красный и оранжевый прекрасный окрас розоватый и красный краснота'''      

Вывод:

         красноватый фиолетовый и красный  зеленый и желтый зеленый желтый и красный зеленый и оранжевый прекрасный окрас розоватый и красный краснота   окрас краснота   желтый желтый прекрасный розоватый      

Решение:

         import re st = '''красноватый фиолетовый и красный  красный и желтый красный желтый и красный красный и оранжевый прекрасный окрас розоватый и красный краснота''' print(re.sub(r'(?<!иs)bкрасныйb', 'зеленый', st), 'n') print(*re.findall(r'bw+b(?<![иый])', st), 'n') print(*re.findall(r'(?![кфо])bw{2,}', st))      

Задание 8

Напишите регулярные выражения, которые:

  1. Удаляют все html-теги из полученной от пользователя строки.
  2. Вставляют пробелы перед заглавными буквами в тексте и ставят точки в конце предложений.

Пример ввода:

         <h1>Это заголовок первого уровня</h1><p>Это текст параграфа<strong>Это важный текст внутри параграфа</strong></p><p>Это второй параграф</p>     

Вывод:

         Это заголовок первого уровня. Это текст параграфа. Это важный текст внутри параграфа. Это второй параграф.     

Решение:

         import re st = input() st = re.sub('<[^<>]+>', '', st) print(re.sub(r'(w)([А-Я]|$)', r'1. 2', st))      

Задание 9

Напишите регулярное выражение для валидации пароля. Надежный пароль имеет длину от 8 до 20 символов и включает в себя хотя бы:

  • один символ в верхнем регистре;
  • один символ в нижнем регистре;
  • одну цифру;
  • один спецсимвол из набора @$!%*#?&.

Пример ввода 1:

         cheBur@sh!ka       

Вывод:

         Ненадежный пароль     

Пример ввода 2:

         cheBur@sh#ka5       

Вывод:

         Надежный пароль     

Решение:

         import re valid = re.compile(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[@$!%*#?&])[A-Za-zd@$!#%*?&]{8,20}$') passw = input() print('Надежный пароль' if valid.fullmatch(passw) else 'Ненадежный пароль')      

Задание 10

Напишите программу, которая получает от пользователя строку с IP-адресом и определяет, является ли этот адрес:

  • корректным IPv4-адресом;
  • корректным IPv6-адресом;
  • адресом некорректного формата.

Корректный IPv4-адрес соответствует формату x1.x2.x3.x4, где 0 <= xi <= 255, и не содержит ведущих нулей. В корректный IPv6 адрес, состоящий из 128 битов, входят восемь групп из четырех шестнадцатеричных цифр; группы разделены двоеточиями.

Пример ввода 1:

         192.168.1.0     

Вывод:

         Корректный IPv4     

Пример ввода 2:

         2001:0db8:85a3:0000:0000:8a2e:0370:7334       

Вывод:

         Корректный IPv6     

Пример ввода 3:

         192.168.1.000       

Вывод:

         Адрес имеет некорректный формат     

Решение:

         import re valid_ip4 = re.compile(r'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])') valid_ip6 = re.compile(r'((([0-9a-fA-F]){1,4}):){7}([0-9a-fA-F]){1,4}') ip = input() if valid_ip4.fullmatch(ip):     print('Корректный IPv4') elif valid_ip6.fullmatch(ip):     print('Корректный IPv6') else:     print('Адрес имеет некорректный формат')      

Подведем итоги

Regex – мощный, но достаточно сложный инструмент: для конструирования и тестирования шаблонов лучше пользоваться специальными сервисами, которые помогают визуализировать результат работы выражения. Во многих случаях регулярные выражения можно заменить методами строк или специальным html/xml/ txt парсером.

В следующей статье будем изучать основы скрапинга и парсинга.

Содержание самоучителя

  1. Особенности, сферы применения, установка, онлайн IDE
  2. Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
  3. Типы данных: преобразование и базовые операции
  4. Методы работы со строками
  5. Методы работы со списками и списковыми включениями
  6. Методы работы со словарями и генераторами словарей
  7. Методы работы с кортежами
  8. Методы работы со множествами
  9. Особенности цикла for
  10. Условный цикл while
  11. Функции с позиционными и именованными аргументами
  12. Анонимные функции
  13. Рекурсивные функции
  14. Функции высшего порядка, замыкания и декораторы
  15. Методы работы с файлами и файловой системой
  16. Регулярные выражения

***

Шпаргалка по регулярным выражениям

reguljarnye vyrazhenija python c1b1b20 - Регулярные выражения Python

Скачать в формате .pdf ***

Материалы по теме

  • 🐍 Регулярные выражения в Python за 5 минут: теория и практика для новичков и не только

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» Интересно, перейти к каналу

  • 4 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close