Регулярки. Как много сокрыто под этим словом, как трудно их осознать. В других языках нужно просто составлять какофонию символов и надеяться что все сработает как нужно. В Python же с этим заморочились и создали целую удобную библиотеку со своими флагами именованными группами и экранированием.
Библиотека, которая нацелена на регулярки называется re и её основные методы: re.search -> ищет первое совпадение в строке и возвращает Match иначе None. re.findall -> ищет все совпадения и возвращает их как список. re.finditer -> возвращает итератор с объектами и Match.re.match -> проверяеттолько начало строки. re.fullmatch -> проверяет полное совпадение строки. re.sub -> заменяет совпадения другой строкой re.split -> разбивает строку по шаблону
Для построения регулярок используется принцип сырой строки, чтобы не экранировать помногу раз всякие слеши. Сырые строки - это приписка r вначале стринга.
#Без сырой строки нужно экранировать дважды:re.search("\d+", "123")
#С сырой строкой — просто:re.search(r"d+", "123")
Что по базовым элементам, нужно их просто запомнить и тогда регулярки получаются уже практически сами собой: . -> это вообще любой символ кроме перевода строки (n). d -> любая цифра от 0 до 9 w -> любая буква, цифра или нижнее подчеркивание s -> пробел [abc] -> любой символ в скобках [^abc] -> любой символ не входящий в скобки
- -> 0 или больше повторений
- -> 1 или больше повторений ? -> 0 или 1 повторение {n,m} -> от n до m повторений ^ -> начало строки $ -> конец строки
Python поддерживает именованные группы для регулярок:
text = "Иван: +7 (123) 456-78-90"<br>match = re.search(r"(?Pw+):s+(?P+ds(d{3})sd{3}-d{2}-d{2})", text)
if match:
print(match.group("name")) # Иван print(match.group("phone")) # +7 (123) 456-78-90
Флаги, они помогают сканить строку именно так как нужно:
re.IGNORECASE (re.I) — игнорирует регистр.
re.MULTILINE (re.M) — ^ и $ работают для каждой строки.
re.DOTALL (re.S) — . включает перевод строки (n).<br>и тд.
re.findall(r"^hello", "Hellonhello", flags=re.I | re.M) # ['Hello', 'hello']
Несколько примеров:
поиск email в тексте:
import re
text = "Пиши на [email1@test.com](email1@test.com) или email2@example.org"
emails = re.findall(r"[w.-]+@[w.-]+.[a-zA-Z]{2,}", text)
print(emails) # ['email1@test.com', 'email2@example.org']Валидация даты:
date = "31-12-2023"
if re.fullmatch(r"d{2}-d{2}-d{4}", date):
print("Дата корректна")
Разбор логов:
log = "192.168.1.1 [2023-01-01 12:00:00] GET /"
match = re.search(r"(?Pd+.d+.d+.d+).*?[(?P.+?)]", log)
print(match.groupdict()) # {'ip': '192.168.1.1', 'time': '2023-01-01 12:00:00'}
Важная инфа:
Нужно быть внимательнее при использовании match() и search(), так как match() ищет только в начале строки, а search() - ищет везде.
По-умолчанию * и + жадные, то есть захватывают все, потому лучше использовать *? для ленивого режима:
text = "testanother"
re.findall(r"(.?)", text) # 'test', 'another'
re.findall(r"(.)", text) # 'testanother'``````