Подтвердить что ты не робот

Regex в python: возможно ли получить совпадение, замену и окончательную строку?

Для выполнения замены регулярных выражений есть три вещи, которые вы им даете:

  • Шаблон соответствия
  • Образец замены
  • Исходная строка

Есть три вещи, которые обнаруживает двигатель регулярных выражений, который меня интересует:

  • Соответствующая строка
  • Строка замены
  • Окончательная обработанная строка

При использовании re.sub конечная строка возвращает результат. Но возможно ли получить доступ к двум другим вещам, согласованной строке и заменой строки?

Вот пример:

orig = "This is the original string."
matchpat = "(orig.*?l)"
replacepat = "not the \\1"

final = re.sub(matchpat, replacepat, orig)
print(final)
# This is the not the original string

Строка соответствия "original", а строка замены - "not the original". Есть ли способ получить их? Я пишу script для поиска и замены во многих файлах, и я хочу, чтобы он печатал его, что он находит и заменяет, не распечатывая всю строку.

4b9b3361

Ответ 1

class Replacement(object):

    def __init__(self, replacement):
        self.replacement = replacement
        self.matched = None
        self.replaced = None

    def __call__(self, match):
        self.matched = match.group(0)
        self.replaced = match.expand(self.replacement)
        return self.replaced

>>> repl = Replacement('not the \\1')
>>> re.sub('(orig.*?l)', repl, 'This is the original string.')
    'This is the not the original string.'
>>> repl.matched
    'original'
>>> repl.replaced
    'not the original'

Изменить:, как указал Ф. Дж., выше будет помнить только последнее совпадение/замена. Эта версия обрабатывает несколько вхождений:

class Replacement(object):

    def __init__(self, replacement):
        self.replacement = replacement
        self.occurrences = []

    def __call__(self, match):
        matched = match.group(0)
        replaced = match.expand(self.replacement)
        self.occurrences.append((matched, replaced))
        return replaced

>>> repl = Replacement('[\\1]')
>>> re.sub('\s(\d)', repl, '1 2 3')
    '1[2][3]'

>>> for matched, replaced in repl.occurrences:
   ....:     print matched, '=>', replaced
   ....:     
 2 => [2]
 3 => [3]

Ответ 2

Я просмотрел документацию и, похоже, вы можете передать ссылку на функцию в re.sub:

import re

def re_sub_verbose(pattern, replace, string):
  def substitute(match):
    print 'Matched:', match.group(0)
    print 'Replacing with:', match.expand(replace)

    return match.expand(replace)

  result = re.sub(pattern, substitute, string)
  print 'Final string:', result

  return result

И я получаю этот вывод при запуске re_sub_verbose("(orig.*?l)", "not the \\1", "This is the original string."):

Matched: original
Replacing with: not the original
This is the not the original string.