用Python re.sub如何仅替换匹配部分

99

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

'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”出现的位置来替换或者最后一个“.”

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


为什么要转义下划线 (\\_a) - Amarghosh
6个回答

135

在你想保留的部分周围加上捕获组,并在替换文本中引用该捕获组。

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

@Amber:从你的回答中我推断出,与str.replace()不同的是,我们不能在原始字符串中使用变量a);或者b)作为re.sub的参数;或者c)两者都不行。a)有道理(我想),但我不确定b)。虽然似乎我们可以使用一个变量名来表示正则表达式所遍历的字符串。你能否详细解释一下?谢谢。 - Malik A. Rumi
哪些部分正在捕获和引用它? - cryanbhu
4
在Python的re包中,“正则表达式语法”文档中,括号内的内容成为一个组。组按出现顺序编号,并且可以通过反斜杠后跟数字进行引用。在例子中,\2引用第二个组。由于在字符串前面添加了r,所以单个反斜杠就足够了,因为这使得它被视为“原始字符串”。如果没有前置r,则\2将引用该组。此外,在“正则表达式语法”文档的相关部分中,(...)和\number也有解释。另外,\的用法在开头已经解释了(截至今天的第三段)。 - ra0

51
 re.sub(r'(?:_a)?\.([^.]*)$', r'_suff.\1', "long.file.name.jpg")
?:表示非捕获组(SO答案),因此(?:_a)匹配_a但不捕获,问号使其变为可选。

换句话说,这个正则表达式的意思是匹配后缀为.<anything>并且遵循模式_a(或不遵循)

还有一种方法是使用回顾后查在这里看看)。提到这个因为它们非常有用,但我在做正则表达式15年中不知道它们存在。


11
将扩展的表达式放入一组中,进行捕获并在替换中引用匹配项:
re.sub(r'(?:_a)?(\.[^\.]*)$' , r'_suff\1',"long.file.name.jpg")

此外,使用非捕获组(?:…)可以防止 re 存储过多不必要的信息。


10

您可以通过排除替换的部分来完成这个操作。我的意思是,您可以告诉正则表达式模块:“匹配这个模式,但替换其中一部分。”

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

long.file.name.jpg部分用于匹配,但它们被排除在替换之外。


回顾先行断言?<=只允许使用固定宽度的模式。如果您有一个,这是一个不错的选择。 - Justin

0
我想使用捕获组来替换字符串的特定部分,以便稍后帮助我解析它。请考虑下面的示例:
s= '<td> <address> 110 SOLANA ROAD, SUITE 102<br>PONTE VEDRA BEACH, FL32082 </address> </td>'

re.sub(r'(<address>\s.*?)(<br>)(.*?\<\/address>)', r'\1 -- \3', s)
##'<td> <address> 110 SOLANA ROAD, SUITE 102 -- PONTE VEDRA BEACH, FL32082 </address> </td>'

-1
print(re.sub('name(_a)?','name_suff','long.file.name_a.jpg'))
# long.file.name_suff.jpg

print(re.sub('name(_a)?','name_suff','long.file.name.jpg'))
# long.file.name_suff.jpg

8
你的回答可以通过添加更多支持性信息来改善。请使用 [编辑] 功能添加更多细节,例如引用或文献资料,以便其他人可以确认你的回答是正确的。你可以在 帮助中心 找到有关如何撰写优质答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接