我的文字如下:
Added "a-foo-b" foo.
目标是使用正则表达式将第二个 foo 替换为 bar,并保持两个双引号之间的第一个 foo 不变。所以在上面的文字中,我正在寻找的结果是:
Added "a-foo-b" bar.
谢谢
我的文字如下:
Added "a-foo-b" foo.
目标是使用正则表达式将第二个 foo 替换为 bar,并保持两个双引号之间的第一个 foo 不变。所以在上面的文字中,我正在寻找的结果是:
Added "a-foo-b" bar.
谢谢
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。替换模式将替换我们匹配的所有内容,但这没关系,因为我们使用 a\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):]