2016-08-03 12 views
3

Я пытаюсь написать функцию Python, которая заменяет экземпляры текста, окруженные фигурными фигурными скобками, содержимым фигурных скобок, оставляя только пустые пары фигурных скобок. Например:Python regex - Заменить текст в скобках с содержимым скобок

foo {} bar {baz} будет foo {} bar baz.

Образец, который я создал, соответствует {[^{}]+}, то есть текст, который не содержит фигурных скобок (для предотвращения совпадений совпадений), окруженных набором фигурных скобок.

Очевидное решение состоит в использовании re.sub с моим рисунком, и я обнаружил, что я могу ссылаться на совпавший текст с \g<0>:

>>> re.sub("{[^{}]+}", "A \g<0> B", "foo {} bar {baz}") 
'foo {} bar A {baz} B' 

Так что это не проблема. Тем не менее, я зациклился на том, как обрезать скобки из ссылочного текста. Если я пытаюсь применять диапазон для замены строки:

>>> re.sub("{[^{}]+}", "\g<0>"[1:-1], "foo{}bar{baz}") 
'foo{}barg<0' 

Диапазон применяется до \g<0> разрешен к совпавшего текста, и обрезает ведущий \ и замыкающие >, оставив только g<0, который не имеет никакого специального имея в виду.

Я также попытался определить функцию для выполнения кадрирования:

def trimBraces(string): 
    return string[1:-1] 

Но, неудивительно, что ничего не изменилось.

>>> re.sub("{[^{}]+}", trimBraces("\g<0>"), "foo{}bar{baz}") 
'foo{}barg<0' 

Что мне здесь не хватает? Спасибо заранее.

ответ

2

Вы можете использовать захватив группу заменить часть матча:

>>> re.sub(r"{([^{}]+)}", r"\1", "foo{}bar{baz}") 
'foo{}barbaz' 
>>> re.sub(r"{([^{}]+)}", r"\1", "foo {} bar {baz}") 
'foo {} bar baz' 
+0

Простой, работает. Спасибо! – halbrd

2

При использовании "\g<0>"[1:-1] в качестве шаблона замены, вы только ломтик "\g<0>"строку, а не фактическое значение этого обратная ссылка относится к.

Если вам нужно использовать «зачистка» подход, вам нужно передать объект данных матч к re.sub:

re.sub("{[^{}]+}", lambda m: m.group()[1:-1], "foo{}bar{baz}") 
# => foo{}barbaz 

См this Python demo. Обратите внимание, что m.group() обозначает \g<0> в вашем шаблоне, то есть все значение соответствия.

Однако, используя capturing groups, является более «органическим» решением, см. alexce's solution.

+1

Спасибо за дополнительную информацию. Всегда хорошо понимать понятия, а не просто знать, что работает :) – halbrd

+1

Обратите внимание, что это решение хорошо, если вы хотите обрезать известное количество символов из строки, сопоставляемой более сложными шаблонами регулярных выражений с чередованием (что было бы приятной заменой для отсутствующей функции сброса ветви в Python 're'). Скажем, вам нужно сопоставить подстроки, например '' ... '' или '' ... ''или' [....] '(но не' [... "' или '' ...." ') и замените на то, что находится внутри этих разделителей. В Python 2.x, 're.sub' будет иметь проблемы с обратным подходом. Python 3.5 're' обрабатывает это:' print (re.sub (r '"([^"] *) "| \' ([^ \ '] *) \' ', r' \ 1 \ 2 '," 'Something' "))' печатает 'Something' в Python 3.5.1. –