3

我的文字如下:

Added "a-foo-b" foo.

目标是使用正则表达式将第二个 foo 替换为 bar,并保持两个双引号之间的第一个 foo 不变。所以在上面的文字中,我正在寻找的结果是:

Added "a-foo-b" bar.

谢谢

4

3 回答 3

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。替换模式将替换我们匹配的所有内容,但这没关系,因为我们使用 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)
于 2012-06-29T08:20:19.380 回答
0

如果您的文本总是以点结尾,您可以尝试以下操作:

echo 'Added "a-foo-b" foo.'  | sed s/foo\.$/bar/g

Added "a-foo-b" bar
于 2012-06-29T08:16:54.357 回答
0

一种使用字符串方法的方法。

>>> s='Added "a-foo-b" foo test'
>>> needle='foo'
>>> rind=s.rfind('foo')
>>> if rind!=-1:
...  s=s[:rind] + needle + s[rind+len(needle):]
于 2012-06-29T09:20:41.160 回答