如何用python re.sub替换匹配的一部分

101 投票
6 回答
106906 浏览
提问于 2025-04-15 22:19

我需要用一个正则表达式来匹配两种情况,并进行替换。

比如说,把 'long.file.name.jpg' 替换成 'long.file.name_suff.jpg'。

还有,把 'long.file.name_a.jpg' 替换成 'long.file.name_suff.jpg'。

我正在尝试做以下操作:

re.sub('(\_a)?\.[^\.]*$' , '_suff.',"long.file.name.jpg")

但是这样做会把扩展名 '.jpg' 去掉,结果变成了

long.file.name_suff,而不是 long.file.name_suff.jpg。我明白这是因为 [^.]*$ 这一部分,但我不能去掉它,因为我需要找到最后一个 '_a' 来替换,或者最后一个 '.'。

有没有办法只替换匹配的一部分呢?

6 个回答

11

只需要把扩展名的表达式放进一个组里,捕获它,然后在替换时引用这个匹配的结果:

re.sub(r'(?:_a)?(\.[^\.]*)$' , r'_suff\1',"long.file.name.jpg")

另外,使用不捕获的组 (?:…) 可以防止正则表达式存储过多不必要的信息。

138

在你想要保留的部分周围加上一个捕获组,然后在替换文本中引用这个捕获组。

re.sub(r'(\_a)?\.([^\.]*)$' , r'_suff.\2',"long.file.name.jpg")
52
 re.sub(r'(?:_a)?\.([^.]*)$', r'_suff.\1', "long.file.name.jpg")

?: 开始一个不匹配的组(SO回答),所以 (?:_a) 是在匹配 _a,但不把它列出来,后面的问号让它变成可选的。

简单来说,这段话的意思是,匹配在 _a 后面(或者不跟)的结尾 .<任何东西>

还有一种方法可以做到这一点,就是使用 回顾点这里看)。提到这个是因为它们非常有用,但我做了15年的正则表达式都不知道这个。

撰写回答