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):]
Другие вопросы по тегам