如何在Python中使用匹配组和变量进行替换
我刚开始学Python。这可能很简单,但我还没找到答案。
rndStr = "20101215"
rndStr2 = "20101216"
str = "Looking at dates between 20110316 and 20110317"
outstr = re.sub("(.+)([0-9]{8})(.+)([0-9]{8})",r'\1'+rndStr+r'\2'+rndStr2,str)
我想要的输出是:
Looking at dates between 20101215 and 20101216
但我得到的是:
P101215101216
这两个rndStr的值其实没什么关系。可以假设它们是随机的或者是用户输入的(我这里用静态值是为了简单起见)。谢谢大家的帮助。
4 个回答
rndStr = "20101215"
rndStr2 = "20101216"
mys = "Looking at dates between {0} and {1}".format(rndStr, rndStr2)
请不要把 str
当作变量名使用;这样会覆盖掉 Python 里内置的 str
类型。
注意,如果你把 rndStr
或 rndStr2
的值改成文本(比如 'abc'),而不是数字,你会得到更接近预期的结果吗?
在你给 re.sub
的表达式中,你有 r'\1'+rndStr+...
。这会组合成 '\1'+'20101215'
,然后它试图引用 \120101215
的回溯引用,这可能不是你想要的结果……
你可以使用命名的回溯引用,这样可以让回溯引用更清晰:
rep1 = "20101215"
rep2 = "20101216"
st = "Looking at dates between 20110316 and 20110317"
print re.sub(r'(?P<fp>.+)[0-9]{8}(?P<lp>.+)[0-9]{8}',
r'\g<fp>'+rep1+r'\g<lp>'+rep2,st)
更好的方法是使用更容易理解的语法,并检查匹配尝试的返回结果:
m=re.search(r'(?P<fp>.+)[0-9]{8}(?P<lp>.+)[0-9]{8}',st)
if m:
print m.group('fp')+rep1+m.group('lp')+rep2 #you could use m.group(1) too
else:
print "no match..."
无论哪种情况,你想要的字符串 Looking at dates between 20101215 and 20101216
都能生成。
关于命名回溯引用的 Python 文档:
(?P<name>...)
这和普通的括号类似,但 通过符号组名 'name',可以在 正则表达式的其他部分访问 该组匹配到的子字符串。组名必须是 有效的 Python 标识符,并且每个 组名在正则表达式中只能定义一次。 一个符号组也是一个编号组,就像 如果该组没有命名一样。因此,在下面的 示例中,名为
'id'
的组也可以被 作为编号组 1 引用。例如,如果模式是
(?P<id>[a-zA-Z_]\w*)
,那么可以通过 组名在匹配对象的方法中引用该组, 比如m.group('id')
或m.end('id')
,同时 也可以在正则表达式本身中通过组名 引用(使用(?P=id)
),以及在 提供给.sub()
的替换文本中 (使用\g<id>
)。
你的反向引用有点模糊。你的替换字符串变成了
\120101215\220101216
这两个数字都挺大的,反向引用起来有点麻烦 :)
要解决这个问题,可以使用这个语法:
r'\g<1>'+rndStr+r'\g<2>'+rndStr2
另外,你的括号用得太多了(如果你像我一样说英式英语,可以叫它“括号”:) - 你不需要在 [0-9]{8}
的部分加括号,因为你并不打算反向引用这些部分:
re.sub("(.+)[0-9]{8}(.+)[0-9]{8}",...
这样就足够了。
(还有,像其他地方提到的,不要把 str
作为变量名。否则你会花很多时间去调试为什么 str.replace()
不再工作。虽然我从来没有遇到过这种情况...绝对没有。 :)
所以整个内容变成:
import re
rndStr = "20101215"
rndStr2 = "20101216"
s = "Looking at dates between 20110316 and 20110317"
outstr = re.sub("(.+)[0-9]{8}(.+)[0-9]{8}", r'\g<1>'+rndStr+r'\g<2>'+rndStr2, s)
print outstr
生成:
Looking at dates between 20101215 and 20101216