Regex заменить текст в Python
У меня текст выглядит так:
Added "a-foo-b" foo.
Цель состоит в том, чтобы использовать регулярное выражение для замены второго foo на bar и оставить первый foo между двумя двойными кавычками нетронутыми. Итак, в приведенном выше тексте результат, который я ищу:
Added "a-foo-b" bar.
Спасибо
3 ответа
import re
pat = re.compile(r'("[^"]+".*)foo')
s = '''Added "a-foo-b" foo.'''
s_new = re.sub(pat, r'\1bar', s)
print(s_new)
Поскольку вы сказали, что цель состоит в том, чтобы оставить один в двойных кавычках в одиночестве, я сосредоточился на двойных кавычках в качестве ключа. Скобки образуют "группу совпадений", в которой сохраняются соответствующие строки; эта группа совпадений сопоставляет двойные кавычки и то, что внутри них, а затем шаблон соответствует второму foo. Шаблон замены заменит все, что мы нашли, но это нормально, потому что мы используем \1
вернуть часть спичечной группы, и тогда мы имеем bar
заменить эту секунду foo
,
Если вы знаете, что не может быть больше двойных кавычек после foo
Вы хотите заменить, это может быть лучше шаблон:
pat = re.compile(r'(".*".*)foo')
Этот шаблон соответствует двойной кавычке, затем чему угодно, затем другой двойной кавычке. Первый шаблон не будет работать, если строка в кавычках содержит экранированные двойные кавычки, но этот будет. Но если вы используете этот шаблон в этой строке:
s = '''Added "a-foo-b" foo. "Wow, another foo"'''
Группа совпадений будет соответствовать второму foo и будет соответствовать третьему foo, даже если это будет в кавычках. Это потому, что сопоставление с образцом является "жадным".
РЕДАКТИРОВАТЬ:
Вопрос: Да, что если s = '''Added "a-foo-b" foo.Deleted "a-foo-b".'''
Ответ: Если шаблон всегда выполняется, вы знаете, что в двойных кавычках не будет экранированных двойных кавычек, и вы можете использовать первый шаблон. Затем вы можете применить несколько шаблонов, чтобы обнаружить и / или заменить все, что вы хотите. pat_added
ниже решает проблему, которую мы хотели решить раньше; это якоря на Added
часть строки, поэтому она не будет ничего делать с Deleted
часть строки. Если вы хотите сопоставить и заменить часть строки внутри кавычек, pat_deleted
показывает, как это сделать; у него есть три группы совпадений, и возвращается первая и последняя, чтобы вы могли заменить среднюю. На самом деле нам не нужна спичечная группа для средней; мы могли бы оставить часть, которую мы заменяем, за пределами группы соответствия, как мы сделали с первым шаблоном.
import re
pat_added = re.compile(r'(Added\s+"[^"]+"\s+)\w+')
pat_deleted = re.compile(r'(Deleted\s+"[a-z]-)([^-]+)(-[a-z]"\.)')
s = '''Added "a-foo-b" foo.Deleted "a-foo-b".'''
s = re.sub(pat_added, r'\1bar', s)
s = re.sub(pat_deleted, r'\1bar\3', s)
print(s)
Если ваш текст всегда заканчивается точкой, вы можете попробовать что-то вроде:
echo 'Added "a-foo-b" foo.' | sed s/foo\.$/bar/g
Added "a-foo-b" bar
Подход со строковыми методами.
>>> s='Added "a-foo-b" foo test'
>>> needle='foo'
>>> rind=s.rfind('foo')
>>> if rind!=-1:
... s=s[:rind] + needle + s[rind+len(needle):]