Можно ли как-то декодировать все группы в re.Match объекте?

Есть байты:

b = b'X:\xce\xa4\x91start\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0ende\x85\n\xe0'

Надо отдельной функцией с помощью регулярки вытащить оттуда декодируемые части и затем работать с декодированными частями (т.е. со строками). Вытащить части - не проблема. Проблема в том, чтобы в возвращённом re.Match декодировать все группы.
Пример:

import re

b = b'X:\xce\xa4\x91start\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0ende\x85\n\xe0'
m = re.search(b"start(?P<decodable>.+)end", b)

print(m['decodable'])  # b'\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0'
print(m[0])  # b'start\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0end'
print(m[1])  # b'\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0'
m = decode_match(m, encoding='utf-8')  # Как реализовать подобное отображение?

# Ожидаемый результат:
print(m['decodable'])  # строка
print(m[0])  # startстрокаend
print(m[1])  # строка

Внутри decode_match вызовов bytes.decode может быть сколько угодно.

Пробовал проитерироваться по m и декодировать, но TypeError: 're.Match' object is not iterable

Пытался ради эксперимента декодировать нулевую группу:

m[0] = m[0].decode()

Но TypeError: 're.Match' object does not support item assignment


Ответы (3 шт):

Автор решения: Михаил Муругов

Пока получилось накидать такую функцию:

from itertools import count
import re

def decode_match(match: re.Match, encoding = 'utf-8') -> dict:
    numeric = dict()
    for i in count():
        try:
            numeric[i] = match[i].decode(encoding)
        except IndexError:
            break
    named = {name: group.decode(encoding) for name, group in match.groupdict().items()}
    return {**numeric, **named}

Но она возвращает dict вместо re.Match. Для моей задачи это подходит, но всё же интересно, как получить re.Match с декодированными группами.

→ Ссылка
Автор решения: CrazyElf

Так то все группы можно декодировать в одну строку:

d = list(map(bytes.decode, m.groups()))

Но присвоить обратно в re.Match ничего всё-равно нельзя.

→ Ссылка
Автор решения: Михаил Муругов

Другой вариант:

import re

def decode_match(match: re.March, encoding='utf-8') -> re.Match:
    decoded_pat = match.re.pattern.decode(encoding)
    return re.match(decoded_pat, match[0].decode(encoding))

Возвращает re.Match объект с декодированными группами, но:

  1. Заново прогоняет регулярку на то, что уже найдено;
  2. Не уверен, что декодирование исходного паттерна вернёт результат, соответствующий паттерну для поиска в декодированной строке.
→ Ссылка