Группа без захвата#
По умолчанию все, что попало в группу, запоминается. Это называется группа с захватом.
Иногда скобки нужны для указания части выражения, которое повторяется. И, при этом, не нужно запоминать выражение.
Например, надо получить MAC-адрес, VLAN и порты из такого лог-сообщения:
In [1]: log = 'Jun 3 14:39:05.941: %SW_MATM-4-MACFLAP_NOTIF: Host f03a.b216.7ad7 in vlan 10 is flapping between port Gi0/5 and port Gi0/15'
Регулярное выражение, которое описывает нужные подстроки:
In [2]: match = re.search(r'((\w \.) \w ).+vlan (\d+).+port (\S+).+port (\S+)', log)
Выражение состоит из таких частей:
- ((\w\.)\w) — сюда попадет MAC-адрес
- \w\. — эта часть описывает 4 буквы или цифры и точку
- (\w\.) — тут скобки нужны, чтобы указать, что 4 буквы или цифры и точка повторяются два раза
- \w — затем 4 буквы или цифры
- .+vlan (\d+) — в группу попадет номер VLAN
- .+port (\S+) — первый интерфейс
- .+port (\S+) — второй интерфейс
Метод groups вернет такой результат:
In [3]: match.groups() Out[3]: ('f03a.b216.7ad7', 'b216.', '10', 'Gi0/5', 'Gi0/15')
Второй элемент, по сути, лишний. Он попал в вывод из-за скобок в выражении (\w\.) .
В этом случае нужно отключить захват в группе. Это делается добавлением ?: после открывающейся скобки группы.
Теперь выражение выглядит так:
In [4]: match = re.search(r'((?:\w \.) \w ).+vlan (\d+).+port (\S+).+port (\S+)', log)
In [5]: match.groups() Out[5]: ('f03a.b216.7ad7', '10', 'Gi0/5', 'Gi0/15')
Python Regex Non-capturing Group
Summary: in this tutorial, you’ll learn about the Python regex non-capturing group to create a group but don’t want to store it in the groups of the match.
Introduction to the Python regex non-capturing group
Regular expressions have two types of groups:
So far, you learned how to use a capturing group to extract information from a bigger match or rematch the previous matched group using a backreference.
To do that, you create a capturing group, you place a pattern (or a rule) inside the parentheses, for example:
(X)
Code language: Python (python)
This syntax captures whatever match X inside the match so that you can access it via the group() method of the Match object.
Sometimes, you may want to create a group but don’t want to capture it in the groups of the match. To do that, you can use a non-capturing group with the following syntax:
(?:X)
Code language: Python (python)
Python Regex no-capturing group example
The following example illustrates how to use the capturing groups to capture the major and minor versions of Python in the string «Python 3.10»
import re s = 'Python 3.10' pattern = '(\d+)\.(\d+)' match = re.search(pattern, s) # show the whole match print(match.group()) # show the groups for group in match.groups(): print(group)
Code language: Python (python)
3.10 3 10
Code language: Python (python)
The following pattern matches one or more digits followed by the literal string (.) and one or more digits:
(\d+)\.(\d+)
Code language: Python (python)
It has two capturing groups. They capture the digits before and after the literal (.):
3 10
Code language: Python (python)
Suppose you don’t want to capture the digits before the literal character (.), you can use a non-capturing group like this:
import re s = 'Python 3.10' pattern = '(?:\d+)\.(\d+)' match = re.search(pattern, s) # show the whole match print(match.group()) # show the groups for group in match.groups(): print(group)
Code language: Python (python)
3.10 10
Code language: Python (python)
In this example, we use the non-capturing group for the first group:
(?:\d+)
Code language: Python (python)
To capture the minor version only, you can ignore the non-capturing group in the first place like this:
import re s = 'Python 3.10' pattern = '\d+\.(\d+)' match = re.search(pattern, s) # show the whole match print(match.group()) # show the groups for group in match.groups(): print(group)
Code language: Python (python)
3.10 10
Code language: Python (python)
So why do you use the non-capturing group anyway? the reason for using the non-capturing group is to save memory, as the regex engine doesn’t need to store the groups in the buffer.
Summary
- Use the regex non-capturing group to create a group but don’t save it in the groups of the match.