re.sub() - 用于替换字符串中最后一个子字符串的正则表达式

10

我正在尝试使用Python中的re.sub替换字符串中最后一个子字符串的出现,但是卡在了正则表达式模式上。有人能帮助我得到正确的模式吗?

String = "cr US TRUMP DE NIRO 20161008cr_x080b.wmv"

或者

String = "crcrUS TRUMP DE NIRO 20161008cr.xml"

我想替换最后一次出现的"cr"和扩展名之前的任何内容。

期望得到的输出字符串是 -

"cr US TRUMP DE NIRO 20161008.wmv"
"crcrUS TRUMP DE NIRO 20161008.xml"

我正在使用 re.sub 进行替换。

re.sub('pattern', '', String)

请给予建议。


“pattern” 是你的模式吗?当然,那样做是行不通的… - l'L'l
请展示您正在使用的实际模式和字符串。 - cco
1
cr(?!.*cr)[^.]* - Washington Guedes
我的模式没有起作用,因为我对正则表达式不是很了解,这也是我没有提到它的原因。 - Sanchit
3个回答

9
使用贪婪量词和捕获组:
re.sub(r'(.*)cr[^.]*', '\\1', input)

1
这很整洁,但如果输入是acr.crt,它将无法工作。 - anubhava
@anubhava:有几种情况这个模式不起作用,你也可以考虑一个带有多个点的文件名。显然,这不是一个万无一失的模式,更多的是一个简单的说明如何使用贪婪性来达到最后出现的位置。一旦你理解了这个思路,就可以针对特定的用例进行改进。 - Casimir et Hippolyte

7

使用 str.rfind(sub[, start[, end]]) 函数的替代方案:

string = "cr US TRUMP DE NIRO 20161008cr_x080b.wmv"
last_position = string.rfind('cr')
string = string[:last_position] + string[string.rfind('.'):]

print(string)  #cr US TRUMP DE NIRO 20161008.wmv

此外,在这种情况下,rfind 速度会更快:
以下是测量结果:
使用str.rfind(...)0.0054836273193359375
使用re.sub(...): 0.4017353057861328

2
在我看来,最好的选择。当不需要时,没有必要使用正则表达式。即使在需要时,是否使用它们也是有争议的…… - spectras
@ spectras,是的,当然可以。此外,在这种情况下它运行得更快。 - RomanPerekhrest

2
你可以使用这个负向预查正则表达式:
repl = re.sub(r"cr((?!cr)[^.])*(?=\.[^.]+$)", "", input);

正则表达式演示

正则表达式简介:

cr         # match cr
(?:        # non-capturing group start
   (?!     # negative lookahead start
      cr   # match cr
   )       # negative lookahead end
   [^.]    # match anything but DOT
)          # non-capturing group end
*          # match 0 or more of matching character that doesn't have cr at next postion
(?=        # positive lookahead start
   \.      # match DOT
   [^.]+   # followed by 1 or more anything but DOT
   $       # end of input
)          # postive lookahead end

1
偶然发现这个排版良好的回答。 - ekydfejj

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