Литералы, метасимволы, экранирование, якоря начала и конца строки
Понимание базового синтаксиса — фундамент для работы с regex. В этой теме изучим литералы, метасимволы, экранирование и якоря.
Литералы — это обычные символы, которые соответствуют самим себе.
import re
# Поиск слова 'cat'
re.search(r'cat', 'The cat sat on the mat') # Найдёт 'cat'
# Поиск последовательности символов
re.search(r'hello', 'hello world') # Найдёт 'hello'Литералы регистрозависимы:
re.search(r'Cat', 'The cat sat') # None — не найдёт (разный регистр)
re.search(r'Cat', 'The Cat sat') # Найдёт 'Cat'Для игнорирования регистра используйте флаг re.IGNORECASE.
Метасимволы — символы со специальным значением в regex:
. ^ $ * + ? { } [ ] \ | ( )
Точка соответствует любому одному символу, кроме новой строки:
re.search(r'c.t', 'cat') # 'cat'
re.search(r'c.t', 'c t') # 'c t' (пробел — тоже символ)
re.search(r'c.t', 'c\nt') # None — точка несоответствует newline
# С флагом DOTALL точкасоответствует и newline:
re.search(r'c.t', 'c\nt', re.DOTALL) # 'c\nt'^ — начало строки, $ — конец строки:
re.search(r'^Hello', 'Hello world') # Найдёт в начале
re.search(r'^Hello', 'Say Hello') # None — не в начале
re.search(r'world$', 'Hello world') # Найдёт в конце
re.search(r'world$', 'world Hello') # None — не в концеС флагом re.MULTILINE якоря работают для каждой строки:
text = """First line
Second line
Third line"""
# Без MULTILINE:
re.search(r'^Second', text) # None
# С MULTILINE:
re.search(r'^Second', text, re.MULTILINE) # Найдёт 'Second'Для поиска метасимволов как литералов используйте обратную косую черту \:
# Поиск точки (например, в доменном имени)
re.search(r'example\.com', 'Visit example.com') # 'example.com'
re.search(r'example.com', 'Visit example.com') # 'exampleXcom' — точкасоответствует любой символ!
# Поиск обратной косой черты
re.search(r'C:\\Users', r'C:\Users\name') # 'C:\Users'
# Поиск специальных символов
re.search(r'\$', 'Price: $100') # '$'
re.search(r'\[', 'array[0]') # '['
re.search(r'\?', 'Who?') # '?'| Последовательность | Значение |
|---|---|
\d | Цифра: [0-9] |
\D | Не цифра: [^0-9] |
\w | Word-символ: [a-zA-Z0-9_] |
\W | Не word-символ: [^a-zA-Z0-9_] |
\s | Пробельный символ: пробел, табуляция, newline |
\S | Не пробельный символ |
\b | Граница слова |
\B | Не граница слова |
Подробно классы символов изучим в следующей теме.
Граница слова — позиция между word-символом (\w) и non-word символом:
re.search(r'\bcat\b', 'The cat sat') # 'cat'
re.search(r'\bcat\b', 'The category') # None — 'cat' внутри слова
re.search(r'\bcat\b', 'cat.') # 'cat' — точка это non-word символ
# Поиск слова в начале/конце
re.search(r'\b\w{4}\b', 'The cat sat') # 'The' — первое 4-буквенное словоre.search(r'^test', 'test case') # 'test' — начало строки
re.search(r'\btest', 'test case') # 'test' — начало слова
re.search(r'test$', 'case test') # 'test' — конец строки
re.search(r'test\b', 'case test') # 'test' — конец словаОператор | означает ИЛИ:
re.search(r'cat|dog', 'I have a cat') # 'cat'
re.search(r'cat|dog', 'I have a dog') # 'dog'
re.search(r'cat|dog', 'I have a bird') # None
# В сочетании с группами
re.search(r'(red|blue|green) car', 'blue car') # 'blue car'Приоритет: альтернатива имеет низкий приоритет, используйте скобки для группировки:
re.search(r'^Subject: (Error|Warning)', 'Subject: Error') # 'Subject: Error'
re.search(r'^Subject: Error|Warning', 'Subject: Warning') # 'Warning' — не то!
# Вторая строкасоответствует 'Warning' в любом месте, а не после 'Subject: 'Скобки группируют элементы для применения квантификаторов или альтернативы:
# Повторение группы
re.search(r'(ab)+', 'ababab') # 'ababab'
# Альтернатива в группе
re.search(r'(Mr|Mrs|Ms)\. \w+', 'Mr. Smith') # 'Mr. Smith'
# Извлечение группы
match = re.search(r'(\d{4})-(\d{2})-(\d{2})', '2024-03-09')
match.groups() # ('2024', '03', '09')Подробнее о группах — в теме 5.
# Простой паттерн для российского телефона
pattern = r'\+7\d{10}'
re.search(pattern, '+79991234567') # '+79991234567'
re.search(pattern, '+7-999-123-45-67') # None — есть дефисы# Минимум 8 символов, только буквы и цифры
pattern = r'^[A-Za-z0-9]{8,}$'
bool(re.match(pattern, 'password123')) # True
bool(re.match(pattern, 'pass')) # False — меньше 8
bool(re.match(pattern, 'pass word')) # False — есть пробелemail = 'user@example.com'
match = re.search(r'@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', email)
domain = match.group(1) # 'example.com'text = 'The quick brown fox jumps over the lazy dog'
# Все 4-буквенные слова
re.findall(r'\b\w{4}\b', text) # ['quick', 'brown', 'jumps', 'over', 'lazy']# Ошибка: точкасоответствует любой символ
re.search(r'file.txt', 'fileXtxt') # Найдёт!
# Правильно: экранируйте точку
re.search(r'file\.txt', 'file.txt') # Найдёт
re.search(r'file\.txt', 'fileXtxt') # None# Ошибка: \b несоответствует пробел, это граница word/non-word
re.search(r'\b \b', 'a b') # None
# Для пробела используйте \s
re.search(r'\s', 'a b') # ' 'text = """line1
line2
line3"""
# Ошибка: ^соответствует только начало всей строки
re.findall(r'^line', text) # ['line'] — только первый
# Правильно: с MULTILINE
re.findall(r'^line', text, re.MULTILINE) # ['line', 'line', 'line']. ^ $ * + ? { } [ ] \ | ( )) имеют специальное значение^ и $соответствует позицию начала/конца строки\ отключает специальное значение метасимволов\b — позиция между word и non-word символом| означает ИЛИ, используйте скобки для группировкиre.MULTILINE для работы с многострочным текстомre.DOTALL чтобы точкасоответствует и newlineВопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.