То, что вы пытаетесь сделать, это очень сложно. И вам на самом деле не нужно использовать группы и обратные ссылки, чтобы просто заменить соответствующий текст другой строкой, как предполагает другой ответ.
Однако, если бы была какая-либо причина, почему простой подход не смог бы правильно определить строки, которые вы хотите заменить, и выражения, которые у вас есть в группах, важны для сопоставления, тогда приведенные ниже могут решить проблему для вас.
>>> prefixes = {
... 1: (r"http://www.w3.org/2002/07/owl#([a-z]+)", r"owl:\2"),
... 3: (r"http://www.w3.org/1999/02/22-rdf-syntax-ns#([a-z]+)", r"rdf:\4"),
... 5: (r"http://www.w3.org/2000/01/rdf-schema#([a-z]+)", r"rdfs:\6"),
... 7: (r"http://schema.org/", "schema"),
... 8: (r"http://www.w3.org/2001/XMLSchema#([a-z]+)", r"xsd:\9"),
... 10: (r"http://purl.org/linked-data/sdmx#([a-z]+)", r"sdmx:\11"),
... 12: (r"http://www.w3.org/XML/1998/namespace", r"xml")
... }
...
>>> test_1 = "http://www.w3.org/XML/1998/namespace"
>>> test_2 = "http://www.w3.org/2000/01/rdf-schema#a"
>>>
>>> expr = '(' + ')|('.join(p[0] for p in prefixes.values()) + ')'
>>>
>>> regex = re.compile(expr)
>>>
>>> regex.findall(test_2)
[('', '', '', '', 'http://www.w3.org/2000/01/rdf-schema#a', 'a', '', '',
'', '', '', '')]
>>> regex.sub(lambda m: m.expand(prefixes[m.lastindex][1]), test_2)
'rdfs:a'
>>> regex.sub(lambda m: m.expand(prefixes[m.lastindex][1]), test_1)
'xml'
>>>
There!
То, что у вас было раньше, не было не работает, потому что результаты сопоставления были определены динамически и не совпадают ни с одним из ключей словаря, в которых есть выражения, которых у целевого текста не будет.
Итак, проблема в том, как связать группу выражений с группой замещающих строк, в которых есть обратные ссылки на группы в выражении.
Я воспользовался преимуществом структура списка групп объекта сопоставления для получения индекса совпадающего выражения. Если я сделаю каждое подвыражение в словаре группой, используя круглые скобки, то re.sub()
создаст объект сопоставления с таким количеством элементов группы в нем для каждого совпадения (см. Строку с regex.findall()
- он показывает, как выглядит список групп совпадений структурированный).
Соответствующее подвыражение представлено в списке сопоставляемых объектов в виде непустой строки в позиции заключенного в скобки подвыражения.
>>> expr = '(' + ')|('.join(p[0] for p in prefixes.values()) + ')'
>>> expr
'(http://www.w3.org/2002/07/owl#([a-z]+))|
(http://www.w3.org/1999/02/22-rdf-syntax-ns#([a-z]+))|
(http://www.w3.org/2000/01/rdf-schema#([a-z]+))|
(http://schema.org/)|
(http://www.w3.org/2001/XMLSchema#([a-z]+))|
(http://purl.org/linked-data/sdmx#([a-z]+))|
(http://www.w3.org/XML/1998/namespace)'
>>> regex.findall(test_2)
[('', '', '', '', 'http://www.w3.org/2000/01/rdf-schema#a', 'a', '', '',
'', '', '', '')]
Поэтому я изменил данные prefixes
структура, чтобы быть словарем с ключом в позиции, которая будет возвращена m.lastindex
- это индекс соответствующего подвыражения в скобках.
Обратные ссылки необходимо было отрегулировать так, чтобы они соответствовали позициям в списке совпадений. Например, \1
работает только для поиска первой группы совпадений в результатах.
Другой особенностью объекта сопоставления, который я использовал, был метод m.expand()
, который преобразует обратные ссылки в группы, на которые они ссылаются.