Без рубрики

Регулярные выражения в питон

Опубликовано

Регулярные выражения (regular expression) или же если быть более точными — устойчивые выражения, позволяют сравнивать строковые значения на совпадение с шаблоном. Это может быть шаблон записи сотового телефона, электронной почты или любая другая информация. Номер телефона обычно должен начинаться с «+» и содержать 10 чисел не учитывая код страны. Электронная почта обязательно должна содержать знак @ и символ точки, после которой указывается доменная зона.

Самую простую проверку корректности электронной почты можно написать используя следующий код

email = input("What's your email? ").strip()

if "@" in email:
    print("Valid")
else:
    print("Invalid")

Функция strip() обрежет невидимые символы слева и справа, после чего мы проверим наличие @ в введённом email. Немного дописав условие, мы можем усложнить проверку и проверять не только знак собаки, но и наличие точки в адресе электронной почты.

email = input("What's your email? ").strip()

if "@" in email and "." in email:
    print("Valid")
else:
    print("Invalid")

Недостаток подобного кода в том, что пользователь может ввести только «@.» данная строка пройдёт проверку на корректность. Можно немного усложнить программу, проверяя наличие символов до знака @.

email = input("What's your email? ").strip()

username, domain = email.split("@")

if username and "." in domain:
    print("Valid")
else:
    print("Invalid")

обратите внимание на то как мы используем метод strip() для определения username и в условии определяем факт наличия точки в домене. Запустите код на проверку и наберите какой-нибудь корректный e-mail. Наберите koddom@gmail и вы увидите, что такой адрес не проходит проверку.

Мы можем сделать более тонкую проверку, доработав немного код.

email = input("What's your email? ").strip()

username, domain = email.split("@")

if username and domain.endswith(".com"):
    print("Valid")
else:
    print("Invalid")

endwith() проверяет, что доменное имя оканчивается на «.com». Но тем не менее это не решает полностью проблему, пользователь может ввести [email protected] и этот e-mail пройдёт проверку.

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

Одна из самых используемых функций библиотеки re это search().

Функция search имеет следующий синтаксис re.search(pattern, string, flags=0). Используем данный образец, чтобы изменить наш текущий код.

import re

email = input("What's your email? ").strip()

if re.search("@", email):
    print("Valid")
else:
    print("Invalid")

Заметьте, наш код не увеличил своей функциональности, а ,скорее, наоборот.

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

  • .(точка) — любой символ, не считая символа перевода строки.
  • * — 0 или более повторений.
  • + — 1 и более повторений.
  • ? — 0 или 1 повторение
  • {m} — m повторений
  • {m,n} — m-n повторений

Попробуем использовать небольшой шаблон из спецсимволов в нашем коде.

import re

email = input("What's your email? ").strip()

if re.search(".+@.+", email):
    print("Valid")
else:
    print("Invalid")

Сразу бросается в глаза, то что мы избавились от переменных username и domain. Но в шаблоне появилось сочетание точки с плюсом .+. Согласно списку выше, такая последовательность говорит о том, что перед знаком собаки могут стоять любые символы в количестве один и более штук. То же самое сочетание стоит после @. Попробуйте использовать e-mail koddom@, для проверки. Он будет некорректным. А вот koddom@gmail уже пройдёт проверку.

Добавим ещё одну деталь нашему шаблону.

import re

email = input("What's your email? ").strip()

if re.search(".+@.+.edu", email):
    print("Valid")
else:
    print("Invalid")

Выглядит лучше, но если мы передадим для проверки koddom@gmail%com, то такой e-mail пройдёт проверку. Дело в том, что у нас не проверяется наличие точки перед доменной зоной.

Продолжим редактировать шаблон.

import re

email = input("What's your email? ").strip()

if re.search(".+@.+\.edu", email):
    print("Valid")
else:
    print("Invalid")

Здесь мы добавили так называемый «escape символ» \ . Он позволяет экранировать точку, следующую за ним, таким образом, что она будет восприниматься как наличие точки в строке, а не как любой символ в исходнике. То есть обратный слеш, как бы, говорит компьютеру: сейчас будет символ, который должен быть в строке. А что если в строке нам нужно, вместо символа точки, проверить наличие буквы «n»?

RAW строки

Если в строке написать \n , то это будет считаться одним символом — символом перевода строки. Но стоит нам сказать компьютеру, что это будет сырая строка, то он будет воспринимать эти два символа по отдельности. Чтобы из обычной строки сделать raw-string, нужно перед кавычками поставить символ r. re.search(r".+@.+\.edu", email). Делается это точно так же как когда мы объявляем форматную строку. Добавив символ r перед строкой в коде мы гарантируем, что комбинации с символом \ будут восприниматься не как спецсимволы, а как два отдельных символа. И теперь \n будет восприниматься как шаблонный символ n.

Возвращаемся к устойчивым выражениям в Python.

Продолжим дальше имитировать ввод пользователем e-mail. Попробуйте ввести что-то типа «мой электронный ящик [email protected]«, и код выдаст вам информацию о том что со строкой всё в порядке и она соответствует шаблону.

Нам следует ужесточить правила проверки следующими символами.

  • ˆ — обозначает начало строки.
  • $ — обозначает конец строки

Добавим эти символы в начало и конец строки соответственно.

import re

email = input("What's your email? ").strip()

if re.search(r"^.+@.+\.edu$", email):
    print("Valid")
else:
    print("Invalid")

Сейчас наш шаблон обозначает, что он строка должна начинаться ( ˆ ) с любого символа кроме пробела, и содержать как минимум один символ( .+ ) , после должен стоять символ собаки ( @ ), потом опять любой символ как минимум один раз, исключая пробел ( .+ ), символы должны закончиться точкой ( \. ) после которой следует доменная зона edu и на этом строка должна закончиться ( $ ).

Теперь строка «мой электронный ящик [email protected]» не пройдёт проверку. Однако, «koddom@@@gmail.com» не вызывает у нашего шаблона никаких подозрений и полностью проходит проверку.

Расширим список символов для создания шаблона.

  • [ ] — перечень допустимых символов
  • [ˆ ] — перечень недопустимых символов
import re

email = input("What's your email? ").strip()

if re.search(r"^[^@]+@[^@]+\.edu$", email):
    print("Valid")
else:
    print("Invalid")

[^@]+ говорит о том что любой символ, кроме собаки должен повториться как минимум один раз.

Однако, @ не единственный символ, которого не должно быть в имени пользователя (ƒыћ÷©₽°љ∆…‘ўѕѓњ†®ќџ). Гораздо проще указать из каких символов может состоять имя пользователя и доменная зона.

import re

email = input("What's your email? ").strip()

if re.search(r"^[a-zA-Z0-9_]+@[a-zA-Z0-9_].+\.edu$", email):
    print("Valid")
else:
    print("Invalid")

[a-zA-Z0-9_] — указывает на любой символ от a до z, от A до Z, от 0 до 9, и может содержать символ нижнего подчёркивания _. + говорит о том что хотя бы один символ должен повториться один или более раз.

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

import re

email = input("What's your email? ").strip()

if re.search(r"^\w+@\w.+\.edu$", email):
    print("Valid")
else:
    print("Invalid")

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

  • \d — любое десятичное число
  • \D — любое не десятичное число
  • \s — символ пробела.
  • \S — непробельный символ.
  • \w — словесный символ. буква, число или нижнее подчёркивание.
  • \W — несловесный символ.

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

import re

email = input("What's your email? ").strip()

if re.search(r"^\w+@\w.+\.(com|edu|gov|net|org)$", email):
    print("Valid")
else:
    print("Invalid")

ещё несколько специальных символов

  • A | B — любое из A или B.
  • (….) — группа
  • (?: …) — группа исключающая вхождения

Чувствительность раскладки.

Вы уже знаете, что строки «com» и «COM» совершенно разные, хотя должны оцениваться как идентичные. В функции re.search() есть параметр flags, он указывается третим по счёту. А вот некоторые доступные константы, которые мы можем использовать.

  1. re.IGNORECASE
  2. re.MULTILINE
  3. re.DOTALL

И теперь, мы можем изменить код следующим образом.

import re

email = input("What's your email? ").strip()

if re.search(r"^\w+@\w.+\.edu$", email, re.IGNORECASE):
    print("Valid")
else:
    print("Invalid")

Теперь [email protected] и [email protected] будут проходить проверку. А как насчёт того чтобы добавить поддоменную зону, допустим, koddom@site.gmail.com. Это ещё один пример, который не пройдёт проверку нашим шаблоном, потому что после @ наш шаблон допускает только одну точку.

Изменим немного шаблон используя ( ) группу.

import re

email = input("What's your email? ").strip()

if re.search(r"^\w+@(\w+\.)?\w+\.edu$", email, re.IGNORECASE):
    print("Valid")
else:
    print("Invalid")

Давайте разберём часть шаблона (\w+\.)? . Мы сразу видим группу () в ней могут повторяться любой из словесный символ \w один или более раз +. Так же словесные символы заканчиваются точкой \. . Так же символ ? в конце, говорит о том, что группа символов может повторяться 0 или 1 раз. Описание ? мы говорили в начале статьи.

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

^[a-zA-Z0-9.!#$%&’*+\/=?^_` {|}~-]+@[a-zA-Z0-9](?:[a-zA -Z0-9-]{0,61}[a-zA-Z0-9])?( ?:\.[a-zA-Z0-9](?:[a-zA-Z0- 9-]{0,61}[a-zA-Z0-9])?)*$

Но давайте не будем разбирать этот шаблон)))