Группы захвата регулярных выражений в Python с примерами
Предположим, у вас есть следующий путь, по которому на веб-сайте отображаются новости с идентификатором 100:
news/100
Следующее регулярное выражение соответствует указанному выше пути:
\w+/\d+
Обратите внимание, что приведенное выше регулярное выражение также соответствует любому пути, который начинается с одного или нескольких словесных символов, например, сообщения, задачи и т. д., а не только новости.
В этом шаблоне:
- \w+ — это набор символов слова с квантификатором(+), который соответствует одному или нескольким символам слова.
- / сравнивает косую черту / символ.
- \d+ — это набор символов цифр с квантификатором(+), который соответствует одной или нескольким цифрам.
Следующая программа использует шаблон \w+/\d+ для соответствия строке «news/100»:
import re s = 'news/100' pattern = '\w+/\d+' matches = re.finditer(pattern,s) for match in matches: print(match)
Выход:
<re.Match object; span=(0, 8), match='news/100'>
Он показывает одно совпадение, как и ожидалось.
- Создание группы захвата регулярных выражений в Python
- Именованные группы захвата
- Пример группы захвата с другим названием
Создание группы захвата регулярных выражений в Python
Чтобы получить идентификатор из пути, вы используете группу захвата. Чтобы определить группу захвата для шаблона, вы помещаете правило в круглые скобки:
(rule)
Например, чтобы создать группу захвата регулярных выражений в Python, которая захватывает идентификатор из пути, вы используете следующий шаблон:
'\w+/(\d+)'
В этом шаблоне мы помещаем правило \d+ внутри круглых скобок(). Если вы запустите программу с новым шаблоном, вы увидите, что она отображает одно совпадение:
import re s = 'news/100' pattern = '\w+/(\d+)' matches = re.finditer(pattern, s) for match in matches: print(match)
Выход:
<re.Match object; span=(0, 8), match='news/100'>
Чтобы получить группы захвата из совпадения, вы используете метод group() объекта Match:
match.group(index)
Группа(0) вернет все совпадение, а группа(1), группа(2) и т. д. вернет первую, вторую и… группу.
Свойство Lastindex объекта Match возвращает последний индекс всех подгрупп. Следующая программа показывает все совпадение (группу(0)) и все подгруппы:
import re s = 'news/100' pattern = '\w+/(\d+)' matches = re.finditer(pattern, s) for match in matches: for index in range(0, match.lastindex + 1): print(match.group(index))
Выход:
news/100 100
В выводе news/100 — это все совпадение, а 100 — это подгруппа.
Если вы хотите также захватить ресурс (новости) по пути(news/100), вы можете создать дополнительную группу захвата следующим образом:
'(\w+)/(\d+)'
В этом шаблоне у нас есть две группы захвата: одна для \w+, а другая для \d+. Следующая программа показывает match.group и все подгруппы:
import re s = 'news/100' pattern = '(\w+)/(\d+)' matches = re.finditer(pattern, s) for match in matches: for index in range(0, match.lastindex + 1): print(match.group(index))
Выход:
news/100 news 100
В выводе news/100 — это все совпадение, а news и 100 — это подгруппы.
Именованные группы захвата
По умолчанию вы можете получить доступ к подгруппе в совпадении, используя индекс, например match.group(1). Иногда доступ к подгруппе по значимому имени оказывается более удобным.
Вы используете именованную группу захвата, чтобы присвоить группе имя. Ниже показан синтаксис присвоения имени группе захвата:
(?P<name>rule)
В этом синтаксисе:
- () указывает на группу захвата.
- ?P указывает имя группы захвата.
- правило — это правило в шаблоне.
Например, следующее создает имена:
'(?P<resource>\w+)/(?P<id>\d+)'
В этом синтаксисе ресурс — это имя первой группы захвата, а идентификатор — имя второй группы захвата.
Чтобы получить все именованные подгруппы совпадения, вы используете метод groupdict() объекта Match. Например:
import re s = 'news/100' pattern = '(?P<resource>\w+)/(?P<id>\d+)' matches = re.finditer(pattern, s) for match in matches: print(match.groupdict())
Выход:
{'resource': 'news', 'id': '100'}
В этом примере метод groupdict() возвращает словарь, где ключами являются имена групп, а значениями — подгруппы.
Пример группы захвата с другим названием
Следующий шаблон:
\w+/d{4}/d{2}/d{2}
соответствует этому пути:
news/2021/12/31
И вы можете добавить именованные группы захвата в шаблон следующим образом:
'(?P<resource>\w+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})'
Эта программа использует шаблоны для сопоставления пути и показывает все подгруппы:
import re s = 'news/2021/12/31' pattern = '(?P<resource>\w+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})' matches = re.finditer(pattern, s) for match in matches: print(match.groupdict())
Выход:
{'resource': 'news', 'year': '2021', 'month': '12', 'day': '31'}