Продвинутые методы использования групп захвата (Advanced Capture Group Techniques)
Помимо основных групп захвата (basic capture groups), Python regex предлагает более продвинутые функции, такие как вложенные группы захвата (nested capture groups), не захватывающие группы (non-capturing groups) и просмотры (lookarounds).
Вложенные группы захвата (Nested Capture Groups)
Группы захвата могут быть вложены в другие группы захвата для извлечения более детальной информации.
Создайте новый файл с именем nested_capture.py в каталоге ~/project.
touch ~/project/nested_capture.py
Откройте nested_capture.py и добавьте следующий код:
import re
def parse_complex_data(text):
pattern = r'((\w+)\s(\w+))\s\[(\d+)\]'
match = re.match(pattern, text)
if match:
full_name = match.group(1)
first_name = match.group(2)
last_name = match.group(3)
id_number = match.group(4)
return {
'full_name': full_name,
'first_name': first_name,
'last_name': last_name,
'id': id_number
}
return None
text = 'John Doe [12345]'
result = parse_complex_data(text)
if result:
print(f"Full Name: {result['full_name']}")
print(f"First Name: {result['first_name']}")
print(f"Last Name: {result['last_name']}")
print(f"ID: {result['id']}")
else:
print("No match found.")
Сохраните файл.
Запустите скрипт.
python ~/project/nested_capture.py
Вывод покажет извлеченные данные, включая полное имя и его компоненты:
Full Name: John Doe
First Name: John
Last Name: Doe
ID: 12345
Здесь ((\w+)\s(\w+)) — это вложенная группа захвата. group(1) захватывает все "John Doe", group(2) захватывает "John", а group(3) захватывает "Doe". group(4) захватывает ID.
Не захватывающие группы (Non-Capturing Groups)
Иногда вам нужно сгруппировать части шаблона (pattern) для применения квантификаторов (quantifiers) или альтернатив, но вам не нужно захватывать содержимое. Не захватывающие группы (?:...) используются для этой цели.
Создайте новый файл с именем non_capturing.py в каталоге ~/project.
touch ~/project/non_capturing.py
Откройте non_capturing.py и добавьте следующий код:
import re
def extract_domain_info(url):
## (?:) creates a non-capturing group
pattern = r'https?://(?:www\.)?([^/]+)'
match = re.match(pattern, url)
if match:
domain = match.group(1) ## Only the domain is captured
return domain
return None
url1 = 'https://www.example.com/path'
domain1 = extract_domain_info(url1)
print(f"Domain from '{url1}': {domain1}")
url2 = 'http://example.org/another/path'
domain2 = extract_domain_info(url2)
print(f"Domain from '{url2}': {domain2}")
Сохраните файл.
Запустите скрипт.
python ~/project/non_capturing.py
Вывод покажет извлеченные доменные имена:
Domain from 'https://www.example.com/path': example.com
Domain from 'http://example.org/another/path': example.org
В этом примере (?:www\.)? соответствует "www.", если он существует, но не захватывает его, поэтому group(1) напрямую захватывает доменное имя.
Использование не захватывающих групп может немного повысить производительность и сохранить индексы захваченных групп более чистыми, когда вам нужно захватить только определенные части большего шаблона.