popov . dev

Главная

Библиотека

Статьи

Полный экскурс п...

Полный экскурс по регулярным выражениям в Python

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

В этой статье мы рассмотрим следующие концепции:

  1. Почему мы используем регулярные выражения?
  2. Что такое регулярные выражения?
  3. Основные операции с регулярными выражениями
  4. Проверка email с помощью регулярных выражений
  5. Проверка номера телефона с помощью регулярных выражений

Зачем использовать регулярные выражения?

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

Рассмотрим следующий сценарий:

У вас есть файл журнала событий, содержащий большое количество данных. И из этого файла журнала вы хотите получить только дату и время. Как вы можете видеть в следующем фрагменте, на первый взгляд, читаемость файла достаточно низкая.

[2024-06-07 06:53:41 +0500][7529][PROD]GET/robots.txt[2024-06-
07 06:53:42 +0500] [7529] [PROD] GET /library/articles/10[2024-
06-07 06:56:16 +0500][7019][PROD]GET / [2024-06-07 07:00:02
+0500][7018][PROD]GET/app/.git/config
[2024-06-07 07:06:04 +0500][7018][PROD]GET /[2024-06-07
07:07:51 +0500][7530][PROD] GET /[2024-06-07 07:12:12 +0500]
[7531] [PROD] GET /robots.txt[2024-06-07 07:15:16 +0500]
[7531] [PROD] GET /currency/XDR[2024-06-07 07:29:10 +0500][7529
][PROD] GET /[2024-06-07 07:39:03 +0500] [7530][PROD]GET/li
brary/articles/26[2024-06-07 07:39:04 +0500][7530][PROD]GE
T/img/get[2024-06-07 08:12:17 +0500][7531][PROD]GET/robots.t
xt[2024-06-07 08:15:05 +0500] [7529][PROD]GET/search/[2024-06-
07 08:15:09 +0500] [7529] [PROD] GET /apps/creativebutton
[2024-06-07 08:15:15 +0500][7529][PROD]GET /currency/CNY[2024-06
-07 08:15:20 +0500] [7529] [PROD] GET /currency/JPY

В этом случае можно использовать регулярные выражения, чтобы легко распознавать шаблоны и извлекать необходимую информацию.

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

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

Следующий сценарий очень похож на тот, что описан в примере с продавцом. Рассмотрим следующее изображение:

Как мы можем проверить номер телефона?

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

Далее следует еще один простой сценарий. База данных студентов.

У нас есть база данных учащихся, содержащая такие данные, как имя, возраст и адрес. Рассмотрим случай, когда код города изначально был 199406, но теперь был изменен на 190000. Вручную обновлять его для каждого учащегося было бы трудоемким и очень длительным процессом.

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

Регулярные выражения можно использовать в большинстве языков:

  1. Java
  2. Python
  3. Ruby
  4. Swift
  5. Scala
  6. Groovy
  7. C#
  8. PHP
  9. Javascript

Существует еще масса сценариев, в которых нам помогают регулярные выражения. Рассмотрим их с вами о них в следующих разделах этой статьи.

Что такое регулярные выражения?

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

Рассмотрим следующий пример:

Имя Фамилия Компания Адрес Город Область Код Телефон Почта
Василий Петров Рога и Копыта Савеловская 1, 256 Санкт-Петербург Санкт-Петербург 190002 +79027652312 v.petrov92@mail.ru
Аркадий Васильев Мечта Транспортная 12, 222 Москва Москва 105005 +79112789009 a.vasiliev00@mail.ru
Елена Ольхова Сторбс-М Раскатная 1 Химки Московская область 124489 +79550981133 elelel@yandex.ru
Александра Корнилова Амакас Пр-кт Космонавтов 12, 9 Екатеринбург Екатеринбург 620012 +79221436756 uchmuchu@bk.ru
Валерий Лерьев Хлебовоз Майская 9 Сызрань Самарская область 446008 +79846578373 sijka99@list.ru
Игорь Степанчук Ортград Школьный пер. 2, 31 Курган Курган 640005 +79674101970 cepoz-apeka21@bk.ru
Юлия Москвина Копейка Социалистическая ул. 55, 9 Ставрополь Ульяновская область 355005 +7933847724 rozex_ejugu73@inbox.ru
Олег Крафт Алабай Пионерская ул. 113, 15 Чита Тамбовская область 672020 +7903724420 coduk_iresa33@yandex.ru
Шамиль Абдулаев РНЛИК Луговой пер. 157, 14 Ижевск Смоленская область 426019 +79044875091 fekuful_umu98@aol.com
Евгений Мартыненко Минтраль Минская ул. 14, 10 Курск Республика Татарстан 305002 +79896197432 fafuca-yuce71@mail.ru

*данные в таблице являются случайной генерацией, совпадение с реальными людьми исключено

Предположим, что из всех данных в данной строке нам нужен только город. Это можно преобразовать в словарь, содержащий только название и город в отформатированном виде. Вопрос теперь в том, можем ли мы определить шаблон для угадывания названия и города? Кроме того, мы можем узнать и возраст. С возрастом все просто, не так ли? это просто целое число.

Что мы будем делать с именем? Если вы посмотрите на шаблон, то увидите, что все имена начинаются с заглавной буквы. С помощью регулярных выражений мы можем определить как имя, так и возраст, используя этот метод.

Рассмотрим следующий код:

import re
 
Nameage = '''
Василисе 22 и Игорю 33
Тамаре 44 и Олегу 21
'''
 
ages = re.findall(r'\d{1,3}', Nameage)
names = re.findall(r'[А-Я][а-я]*',Nameage)
 
ageDict = {}
x = 0
for eachname in names:
    ageDict[eachname] = ages[x]
    x+=1

print(ageDict)

Сейчас нет необходимости беспокоиться о синтаксисе, но поскольку Python обладает потрясающей удобочитаемостью, вы вполне можете догадаться, что происходит с частью кода, содержащей регулярные выражения.

Вывод

{'Василисе': '22', 'Игорю': '33', 'Тамаре': '44', 'Олегу': '21'}

Операции, которые вы можете выполнять с помощью регулярных выражений

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

Поиск слова в строке

Рассмотрим следующий фрагмент кода:

import re
 
if re.search('информ', 'нам нужно проинформировать его о самой свежей информации'):
    print('Здесь есть сообщить!')

Все, что мы здесь делаем, - это ищем, есть ли в нашей поисковой строке слово "информ". И если оно есть, то мы получаем вывод о том, что оно здесь присутствует.

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

import re
 
allinform = re.findall('информ', 'нам нужно проинформировать его о самой свежей информации')
 
for i in allinform:
    print(i)

Здесь, в данном случае, слово "информ" будет найдено дважды. Одно в слове "проинформировать", а другое - в "информации".

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

Создание итератора

Генерация итератора - это простой процесс определения начального и конечного индексов строки и представления отчета о них. Рассмотрим следующий пример:

import re
 
Str = "нам нужно проинформировать его о самой свежей информации"
 
for i in re.finditer("информ.", Str):
    locTuple = i.span()
    print(locTuple)

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

(13, 20)
(46, 53)

Довольно просто, не так ли?

Нахождение слов с помощью шаблонов

Рассмотрим входную строку, в которой вам нужно сопоставить определенные слова со строкой. Рассмотрим следующий пример кода:

import re
 
Str = "Суб, суп, сук, суд"
 
allStr = re.findall("су[бпкд]", Str)
 
for i in allStr:
    print(i)

Что общего в этой строке? Вы можете видеть, что буквы "с" и "у" являются общими для всех входных строк. [бпкд] в коде обозначает конечную букву слов, которые нужно найти. Таким образом, любая подстрока, заканчивающаяся на букву б, п, к или д, будет рассматриваться на предмет соответствия. Любая из этих подстрок, перед которой обязательно стоит в начале "су".

Вывод

суп
сук
суд

Обратите внимание, что все они чувствительны к регистру. По этой причине первое слово не попало под шаблон, так как начинается с большой буквы.

Совпадающий ряд из диапазона символов

Мы хотим вывести все слова, начинающиеся с су и заканчивающиеся на букву, которая должна заканчиваться между к и п (ряд из русского алфавита). Проверяя следующий пример, мы должны понять, что в результате мы должны получить "суп" и "сук", верно?

import re
 
Str = "суб, суп, сук, суд"
 
allStr = re.findall("су[к-п]", Str)
 
for i in allStr:
    print(i)

Давайте теперь немного изменим приведенную выше программу, чтобы получить совсем другой результат. Ознакомьтесь с приведенным ниже кодом и попытайтесь уловить разницу между приведенным выше и приведенным ниже:

import re
 
Str = "суб, суп, сук, суд"
 
allStr = re.findall("[^су][к-п]", Str)
 
for i in allStr:
    print(i)

Здесь мы поменяли шаблон поиска. Такой код выведет пустой результат, а все потому что в начале хоть мы и предполагаем что строка начинается с символов су, однако символ ^ означает самое начало строки. Соответственно единственное что могло бы попасть под фильтр - слово суб, но у него на конце буква б, не входящая в диапазон букв от к до п.

Замена строки

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

import re
 
Food = "суб суп сук суд"
 
regex = re.compile("су[п]")
 
Food = regex.sub("еда", Food)
 
print(Food)

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

Вывод

суб еда сук суд

Проблема обратного слэша

Рассмотрим пример кода, показанный ниже:

import re
 
randstr = "Здесь \\Popov.Dev"
 
print(randstr)

Вывод

Здесь \Popov.Dev

Это проблема с обратным слэшем. Одна из этих символов исчез из вывода. Эту конкретную проблему можно устранить с помощью регулярных выражений.

import re
 
randstr = "Здесь \\Popov.Dev"
 
print(re.search(r"\\Popov.Dev", randstr))

Вывод будет следующим:

<re.Match object; span=(6, 16), match='\\Popov.Dev'>

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

Совпадение с одним символом

С помощью регулярных выражений можно легко подобрать отдельный символ из строки. Ознакомьтесь со следующим фрагментом кода:

import re
 
randstr = "12345"
 
print("Найдено: ", len(re.findall("\d{5}", randstr)))

Ожидаемый результат - 5-е число, которое встречается во входной строке.

Вывод

Найдено: 1

Удаление пробелов в новой строке

Мы можем легко удалить пробелы в новой строке, используя регулярные выражения в Python. Рассмотрим другой фрагмент кода, показанный здесь:

import re
 
randstr = '''
Отчего так
В России
Березы шумят?
'''
 
print(randstr)
 
regex = re.compile("\n")
 
randstr = regex.sub(" ", randstr)
 
print(randstr)

Вывод

Отчего так
В России
Березы шумят?

Отчего так В России Березы шумят?

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

Есть много других возможностей, которые вы могли бы использовать, в зависимости от того, чем вы хотите заменить строку. Они перечислены ниже:

  1. \b: Возврат на один символ
  2. \f: Конец страницы
  3. \r: Возврат каретки
  4. \t: Табуляция
  5. \v: Вертикальная табуляция

Рассмотрим другой пример:

import re
 
randstr = "12345"
 
print("Найдено: ", len(re.findall("\d", randstr)))

Вывод

Найдено: 5

Как вы можете видеть из приведенного выше вывода, \d соответствует числам, присутствующим в строке. Однако, если мы заменим его на \D, оно будет соответствовать всему, кроме целого числа, что является полной противоположностью \d.

Практические примеры использования регулярных выражений

Мы рассмотрим 3 основных варианта использования, которые широко используются на ежедневной основе. Ниже приведены кейса, которые мы рассмотрим:

  1. Верификация номера телефона
  2. Верификация адреса электронной почты

Верификация номера телефона

Задача: необходимость простой проверки телефонных номеров в любом соответствующем сценарии. Имеются следующие данные:

  1. +7 9022443344
  2. +79663125322
  3. 8-9112735634
  4. 89492459900
  5. +7 8424332222
  6. +79445674752
  7. +79855762432
  8. +79997643212

Общий формат телефонного номера выглядит следующим образом:

  1. Начинается с +7 либо с 8
  2. Код страны отделяется пробелом, символом - или просто пробелом
  3. Далее следуют 3 цифры оператора или кода города
  4. Оставшаяся часть состоит из 7 цифр

Для этого нам потребуется следующий шаблон ^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7}$. Он не идеален, но для задачи поиска российских номеров соответствующих базовым правилам он подходит. Для практики, поместим список номеров в переменную phones и пройдемся по ней с помощью регулярных выражений.

import re
phones = """
+7 9022443344
+79663125322
8-9112735634
89492459900
+7 8424332222
+79445674752
+79855762432
+79997643212
"""

regex = re.compile(r"^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7}$")

for item in phones.split('\n'):
    if regex.search(item):
        print(f"Номер правильный: {regex.search(item).group()}")

Вывод

Номер правильный: +7 9022443344
Номер правильный: +79663125322
Номер правильный: 89112735634
Номер правильный: 89492459900
Номер правильный: +7 8424332222
Номер правильный: +79445674752
Номер правильный: +79855762432
Номер правильный: +79997643212

Валидация адреса электронной почты

Задача: необходимость простой проверки Email адресов в любом соответствующем сценарии. Имеются следующие данные:

  1. Petya93@mail.ru
  2. Venija @ com
  3. Bp .com
  4. 321 @.com

Вручную вам достаточно одного внимательного взгляда, чтобы отличить действительные почтовые адреса от недействительных. Но как обстоит дело с тем, что наша программа делает это за нас? Это довольно просто, учитывая, что в данном случае используются следующие рекомендации.

Все адреса электронной почты должны содержать:

  1. От 1 до 20 строчных и/или прописных букв, цифр, точки и нижние подчеркивания в логине
  2. Символ @
  3. От 2 до 20 строчных и прописных букв, цифр в адресе домена
  4. Символ точки
  5. от 2 до 3 строчных и прописных букв

Для этого нам потребуется следующий шаблон [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,3}. Для практики, поместим список адресов в переменную emails и пройдемся по ней с помощью регулярных выражений.

import re

emails = """
Petya93@mail.ru
Venija @ com
Bp .com
321 @.com
"""

regex = re.compile('[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,3}')

for item in emails.split('\n'):
    if regex.search(item):
        print(f"Нашел: {regex.search(item).group()}")

Вывод

Нашел: Petya93@mail.ru

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

Заключение

Я надеюсь, что это руководство по регулярным выражениям Python поможет вам изучить все основы, необходимые для начала использования регулярных выражений в Python. Это будет вспомогательным материалом, когда вы будете разрабатывать приложения, требующие использования регулярных выражений и аналогичных принципов.

Комментарии

Для того чтобы оставить свое мнение, необходимо зарегистрироваться на сайте