Python - Регулярные выражения
Приветствуем, будущие маги Python! Сегодня мы отправляемся в захватывающее путешествие в мир регулярных выражений (regex) в Python. Не волнуйтесь, если вы никогда не слышали о regex раньше - к концу этого урока вы сможете мастерски использовать этот мощный инструмент!
Что такое регулярные выражения?
Перед тем как погружаться в тему, давайте понимем, что такое регулярные выражения. Представьте себе, что вы детектив, который пытается найти определенный шаблон в море текста. Регулярные выражения - это как ваше увеличительное стекло, помогающее искать и манипулировать строками на основе шаблонов. Круто, правда?
Сырые строки
В Python, работая с regex, мы часто используем сырые строки. Они начинаются с символа 'r' и обрабатывают символы обратной косой черты как литеральные символы. Это особенно полезно в regex, так как обратные косые черты встречаются часто.
# Обычная строка
print("Hello\nWorld")
# Сырая строка
print(r"Hello\nWorld")
В первом случае вы увидите "Hello" и "World" на разных строках. Во втором случае вы увидите "Hello\nWorld" как есть. Это становится критически важным при работе с шаблонами regex.
Метасимволы
Метасимволы - это строительные блоки regex. У них есть особое значение, и они помогают нам определять шаблоны. Давайте рассмотрим некоторые из них:
Метасимвол | Значение |
---|---|
. | Совпадает с любым символом, кроме новой строки |
^ | Совпадает с началом строки |
$ | Совпадает с концом строки |
* | Совпадает 0 или более повторений |
+ | Совпадает 1 или более повторений |
? | Совпадает 0 или 1 повторение |
{} | Совпадает с явно указанным количеством повторений |
[] | Указывает набор символов для совпадения |
\ | Экранирует специальные символы |
Функция re.match()
Функция re.match()
пытается найти совпадение шаблона в начале строки. Если она находит совпадение, она возвращает объект совпадения; в противном случае возвращает None.
import re
result = re.match(r"Hello", "Hello, World!")
if result:
print("Совпадение найдено:", result.group())
else:
print("Нет совпадения")
Это выведет "Совпадение найдено: Hello". Метод group()
возвращает совпадающую подстроку.
Функция re.search()
В то время как re.match()
ищет совпадение в начале строки, re.search()
сканирует всю строку для поиска совпадения.
import re
result = re.search(r"World", "Hello, World!")
if result:
print("Совпадение найдено:", result.group())
else:
print("Нет совпадения")
Это выведет "Совпадение найдено: World".
Сравнение match() и search()
Основное различие между match()
и search()
заключается в том, что match()
проверяет совпадение только в начале строки, в то время как search()
проверяет совпадение где угодно в строке.
Функция re.findall()
Функция re.findall()
возвращает все не перекрывающиеся совпадения шаблона в строке в виде списка.
import re
text = "The rain in Spain falls mainly in the plain"
result = re.findall(r"ain", text)
print(result)
Это выведет ['ain', 'ain', 'ain']
.
Функция re.sub()
Функция re.sub()
заменяет все вхождения шаблона в строке на строку замены.
import re
text = "The rain in Spain"
result = re.sub(r"a", "o", text)
print(result)
Это выведет "The roin in Spoin".
Функция re.compile()
Функция re.compile()
создает объект regex для повторного использования, что может быть более эффективным, если вы используете один и тот же шаблон многократно.
import re
pattern = re.compile(r"\d+")
result1 = pattern.findall("There are 123 apples and 456 oranges")
result2 = pattern.findall("I have 789 bananas")
print(result1)
print(result2)
Это выведет ['123', '456']
и ['789']
.
Функция re.finditer()
Функция re.finditer()
возвращает итератор, выдающий объекты совпадения для всех не перекрывающихся совпадений шаблона в строке.
import re
text = "The rain in Spain"
for match in re.finditer(r"ain", text):
print(f"Найдено '{match.group()}' в позиции {match.start()}-{match.end()}")
Это выведет:
Найдено 'ain' в позиции 5-8
Найдено 'ain' в позиции 17-20
Примеры использования Python Regex
Регулярные выражения имеют множество практических применений. Рассмотрим общий случай использования:
Найти слова, начинающиеся с гласных
import re
text = "An apple a day keeps the doctor away"
vowel_words = re.findall(r'\b[aeiouAEIOU]\w+', text)
print(vowel_words)
Это выведет ['An', 'apple', 'a', 'away']
.
Модификаторы регулярных выражений: флаги опций
Модуль re Python предоставляет несколько флагов опций, которые изменяют интерпретацию шаблонов:
Флаг | Описание |
---|---|
re.IGNORECASE (re.I) | выполняет нечувствительное к регистру сравнение |
re.MULTILINE (re.M) | делает ^ совпадающим с началом каждой строки и $ концом каждой строки |
re.DOTALL (re.S) | делает . совпадающим с любым символом, включая новую строку |
re.VERBOSE (re.X) | позволяет писать более читаемые шаблоны regex |
Регулярные выражения шаблонов
Рассмотрим некоторые более сложные шаблоны:
Классы символов
Классы символов позволяют указывать набор символов для совпадения:
import re
text = "The quick brown fox jumps over the lazy dog"
result = re.findall(r"[aeiou]", text)
print(result)
Это выведет все гласные буквы, найденные в тексте.
Специальные классы символов
Python regex поддерживает специальные классы символов:
Класс | Описание |
---|---|
\d | совпадает с любым десятичным числом |
\D | совпадает с любым нецифровым символом |
\s | совпадает с любым пробельным символом |
\S | совпадает с любым не пробельным символом |
\w | совпадает с любым буквенно-цифровым символом |
\W | совпадает с любым не буквенно-цифровым символом |
Повторения
Мы можем указать, сколько раз должен встречаться шаблон:
import re
text = "I have 111 apples and 22 oranges"
result = re.findall(r"\d{2,3}", text)
print(result)
Это выведет ['111', '22']
, совпадая с числами с 2 или 3 цифрами.
Ненасыщенные повторения
По умолчанию повторение является насыщенным, то есть совпадает с максимально возможным количеством повторений. Добавление ? после повторения делает его ненасыщенным:
import re
text = "<h1>Title</h1><p>Paragraph</p>"
greedy = re.findall(r"<.*>", text)
non_greedy = re.findall(r"<.*?>", text)
print("Насыщенное:", greedy)
print("Ненасыщенное:", non_greedy)
Это покажет разницу между насыщенным и ненасыщенным совпадением.
Группировка с помощью скобок
Скобки позволяют группировать части regex:
import re
text = "John Smith ([email protected])"
result = re.search(r"(\w+) (\w+) \((\w+@\w+\.\w+)\)", text)
if result:
print(f"Полное имя: {result.group(1)} {result.group(2)}")
print(f"Электронная почта: {result.group(3)}")
Это извлекает имя и адрес электронной почты из текста.
Обратные ссылки
Обратные ссылки позволяют ссылаться на ранее совпадающие группы:
import re
text = "<h1>Title</h1><p>Paragraph</p>"
result = re.findall(r"<(\w+)>.*?</\1>", text)
print(result)
Это совпадает с открывающими и закрывающими тегами HTML.
Альтернативы
Символ | позволяет указывать альтернативы:
import re
text = "The color of the sky is blue or gray"
result = re.search(r"blue|gray", text)
if result:
print(f"Найден цвет: {result.group()}")
Это совпадает либо с "blue", либо с "gray".
Привязки
Привязки указывают позиции в тексте:
import re
text = "Python is awesome"
start = re.match(r"^Python", text)
end = re.search(r"awesome$", text)
print(f"Начинается с Python: {bool(start)}")
print(f"Заканчивается на awesome: {bool(end)}")
Это проверяет, начинается ли текст с "Python" и заканчивается ли на "awesome".
Специальная синтаксис с помощью скобок
Скобки могут использоваться не только для группировки:
- (?:...) создает некаптурирующую группу
- (?P
...) создает именованную группу - (?=...) создает положительное предварительное совпадение
- (?!...) создает отрицательное предварительное совпадение
import re
text = "Python version 3.9.5"
result = re.search(r"Python (?:version )?(?P<version>\d+\.\d+\.\d+)", text)
if result:
print(f"Версия: {result.group('version')}")
Это извлекает номер версии, будь то "version" присутствует в тексте или нет.
Итак, это было наше путешествие по миру Python regex, от основ к более сложным концепциям. Помните, как и любое мощное инструмент, regex требует практики для мастерства. Так что не расстраивайтесь, если в начале это кажется сложным. Продолжайте экспериментировать, и скоро вы сможете искать шаблоны как настоящий сыщик! Удачи в кодинге!
Credits: Image by storyset