Можно ли как-то декодировать все группы в 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 с декодированными группами.
Так то все группы можно декодировать в одну строку:
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 объект с декодированными группами, но:
- Заново прогоняет регулярку на то, что уже найдено;
- Не уверен, что декодирование исходного паттерна вернёт результат, соответствующий паттерну для поиска в декодированной строке.