Группа создается путем заключения части регулярного выражения в круглые скобки. Это означает, что группа может быть задана в качестве аргумента метасимволам, таким как * и ?.

import re

pattern = r"egg(spam)*"

if re.match(pattern, "egg"):
    print("Match 1")

if re.match(pattern, "eggspamspamspamegg"):
    print("Match 2")

if re.match(pattern, "spam"):
    print("Match 3")

Содержание групп можно получить с помощью функции group. Вызов метода group(0) или group() возвращает все найденные совпадения. Вызов метода group(n), где n больше 0, возвращает n-ю группу, считая слева. Метод groups() возвращает все группы, начиная с первой.

import re

pattern = r"a(bc)(de)(f(g)h)i"

match = re.match(pattern, "abcdefghijklmnop")
if match:
    print(match.group())
    print(match.group(0))
    print(match.group(1))
    print(match.group(2))
    print(match.groups())

Есть несколько типов специальных групп. 

Два наиболее важных: именованные группы и «незахватывающие» группы.

Формат именованных групп: (?P<name>…), где name – имя группы, а … – содержание группы. У них точно такая же функциональность, как и у обычных групп, но их можно получить не только по номеру, но и с помощью метода group(name).

Формат «незахватывающих» групп: (?:…). Их нельзя получить по методу группы, поэтому их можно добавлять в регулярное выражение, не нарушая нумерацию.

import re

pattern = r"(?P<first>abc)(?:def)(ghi)"

match = re.match(pattern, "abcdefghi")
if match:
    print(match.group("first"))
    print(match.groups())

Другой важный метасимвол: |.

Он имеет значение «или»; так в результате выражения красный|синий вернется либо «красный» или «синий».

import re

pattern = r"gr(a|e)y"

match = re.match(pattern, "gray")
if match:
    print ("Match 1")

match = re.match(pattern, "grey")
if match:
    print ("Match 2")    

match = re.match(pattern, "griy")
if match:
     print ("Match 3")

В регулярных выражениях также используются различные специальные последовательности. Их синтаксис записывается как бэкслэш, за которым следует другой символ. 

Одна такая специальная последовательность: бэкслэш и число между от 1 до 99, например, \1 или \17. Такая последовательность соответствует выражению группы с таким же числом.

import re

pattern = r"(.+) \1"

match = re.match(pattern, "word word")
if match:
    print ("Match 1")

match = re.match(pattern, "?! ?!")
if match:
    print ("Match 2")    

match = re.match(pattern, "abc cde")
if match:
    print ("Match 3")

Обратите внимание, что (.+) \1 – не то же самое, что (.+) (.+), потому что \1 относится к подвыражению первой группы, которое само по себе является совпавшим выражением, а не набором символов регулярного выражения.

Есть другие специальные последовательности: \d, \s и \w.

Они означают соответственно цифры (d от англ. digits), пробелы (s от spaces) и символы слов (w от word characters). 

В режиме ASCII им соответствуют [0-9], [ \t\n\r\f\v] и [a-zA-Z0-9_].

В режиме Unicode они соответствуют также некоторым другим символам. Например, \w соответствует символам с диакритикой.

Если эти специальные последовательности записаны с заглавными буквами (\D, \S и \W), они имеют противоположное значение. Например, \D совпадет с любыми символами, кроме цифр.

import re

pattern = r"(\D+\d)"

match = re.match(pattern, "Hi 999!")
if match:
    print("Match 1")

match = re.match(pattern, "1, 23, 456!")
if match:
    print("Match 2")

match = re.match(pattern, " ! $?")
if match:
    print("Match 3")

Среди других специальных последовательностей: \A, \Z и \b.

Последовательности \A и \Z означают соответственно начало и конец строки. 

Последовательность \b соответствует пустой строке между символами \w и \W, или символами \w и началом или концом строки. Также неформально она означает словораздел.

Последовательность \B соответствует пустой строке в любом другом месте.

import re

pattern = r"\b(cat)\b"

match = re.search(pattern, "The cat sat!")
if match:
    print ("Match 1")

match = re.search(pattern, "We s>cat<tered?")
if match:
    print ("Match 2")
match = re.search(pattern, "We scattered.")
if match:
    print ("Match 3")

В качестве демонстрации использования регулярных выражений, напишем программу извлечения адресов электронной почты из программной строки.

Предположим, у нас есть некоторый текст, содержащий адреса электронной почты:

str = "Please contact info@devopser.online for assistance"

Наша задача состоит в том, чтобы извлечь подстроку «info@devopser.online».

Как правило, адрес электронной почты состоит из слов и может содержать точки или черточки. Далее следует знак @ и имя домена (имя, точка и суффикс доменного имени).

Возмем это в качестве основы для нашего регулярного выражения.

pattern = r"([\w\.-]+)@([\w\.-]+)(\.[\w\.]+)"

[\w\.-]+ соответствует одному или более символу слова, точке или черточке.

В регулярном выражении выше указано, что строка должна содержать слово (возможно, с точками и черточками), затем знак @, другое слово, точку и еще одно слово.

Соберем все фрагменты кода вместе:

import re

pattern = r"([\w\.-]+)@([\w\.-]+)(\.[\w\.]+)"
str = "Please contact info@devopser.online for assistance"

match = re.search(pattern, str)
if match:
    print(match.group())

Если строка содержит несколько адресов электронной почты, мы могли бы использовать метод re.findall вместе