Python 正则表达式替换匹配字符串的一部分

10 投票
5 回答
18636 浏览
提问于 2025-04-16 08:47

我有一个字符串,可能看起来像这样

"myFunc('element','node','elementVersion','ext',12,0,0)"

我目前在检查这个字符串的有效性,使用的方法效果很好

myFunc\((.+?)\,(.+?)\,(.+?)\,(.+?)\,(.+?)\,(.+?)\,(.+?)\)

现在我想替换第三个参数里的字符串。不过很不幸,我不能直接在第三个位置上用字符串替换,因为这个“子字符串”可能在这个字符串的其他地方也出现过。

通过这个和一个 re.findall 的方法,

myFunc\(.+?\,.+?\,(.+?)\,.+?\,.+?\,.+?\,.+?\)

我能获取到第三个位置的子字符串内容,但 re.sub 并没有替换字符串,它只是返回了我想替换的字符串 :/

这是我的代码

myRe = re.compile(r"myFunc\(.+?\,.+?\,(.+?)\,.+?\,.+?\,.+?\,.+?\)")
val =   "myFunc('element','node','elementVersion','ext',12,0,0)"

print myRe.findall(val)
print myRe.sub("noVersion",val)

你们觉得我漏掉了什么吗?

谢谢!

5 个回答

2

查看文档:re.sub 会返回一个字符串的副本,其中每个符合模式的部分都会被替换成你指定的内容。它不能修改原始字符串,因为在Python中,字符串是不可变的,也就是说一旦创建就不能改变。

可以尝试使用前瞻和后顾断言来构建一个正则表达式,这样它只匹配你想要的那个元素:

myRe = re.compile(r"(?<=myFunc\(.+?\,.+?\,)(.+?)(?=\,.+?\,.+?\,.+?\,.+?\))")
4

如果你只有一把锤子,那所有的问题看起来都像钉子。正则表达式就像一把强力锤子,但并不是每个任务都适合用它来解决。

有些任务用解析器处理会更好。在这种情况下,字符串中的参数列表就像Python中的元组,所以你可以“作弊”:使用Python自带的解析器:

>>> strdata = "myFunc('element','node','elementVersion','ext',12,0,0)"
>>> args = re.search(r'\(([^\)]+)\)', strdata).group(1)
>>> eval(args)
('element', 'node', 'elementVersion', 'ext', 12, 0, 0)

如果你不能完全信任输入数据,ast.literal_eval比eval更安全。一旦你把字符串中的参数列表拆解开来,我想你就能搞明白如何操作和重新组合它,如果需要的话。

9

在使用 re.sub 的时候,你需要为整个匹配到的字符串指定一个替换内容。这就意味着你需要把那些不想替换的部分也重复写出来。这样做是有效的:

myRe = re.compile(r"(myFunc\(.+?\,.+?\,)(.+?)(\,.+?\,.+?\,.+?\,.+?\))")
print myRe.sub(r'\1"noversion"\3', val)

撰写回答