Ответ 1
Для постоянного регулярного выражения, подобного вашему примеру, выполните
re.sub("(this)(.*)(string)",
r'<markup>\1</markup>\2<markup>\3</markup>',
text)
Обратите внимание, что вам также нужно заключить. * в круглых скобках, если вы не хотите его потерять.
Теперь, если вы не знаете, как выглядит регулярное выражение, это сложнее, но должно быть выполнимо.
pattern = "(this)(.*)(string)"
re.sub(pattern,
lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 0
else s for n, s in enumerate(m.groups())),
text)
Если первое, что соответствует вашему шаблону, необязательно должно быть помечено, используйте его вместо этого, при этом первая группа будет необязательно соответствовать некоторому префиксному тексту, который следует оставить в покое:
pattern = "()(this)(.*)(string)"
re.sub(pattern,
lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 1
else s for n, s in enumerate(m.groups())),
text)
Вы получаете идею.
Если ваши регулярные выражения сложны, и вы не уверены, что можете сделать все, что входит в группу, где только каждая вторая группа должна быть помечена, вы можете сделать что-то умнее с более сложной функцией:
pattern = "(this).*(string)"
def replacement(m):
s = m.group()
n_groups = len(m.groups())
# assume groups do not overlap and are listed left-to-right
for i in range(n_groups, 0, -1):
lo, hi = m.span(i)
s = s[:lo] + '<markup>' + s[lo:hi] + '</markup>' + s[hi:]
return s
re.sub(pattern, replacement, text)
Если вам нужно обрабатывать перекрывающиеся группы, вы сами по себе, но это должно быть выполнимо.