如何从字符串的末尾删除子字符串(删除字符串的后缀)?

562

7
__strip__会将给定的字符从字符串两端去除,对于你的情况,它会去除"."、"c"、"o"和"m"。 - mthurlin
7
它还会从字符串前面删除那些字符。如果你只希望从结尾处删除,请使用 rstrip()。 - Andre Miller
61
是的,str.strip并不是你想象中的那样。str.strip会从字符串的开头和结尾删除指定的任何字符。因此,"acbacda".strip("ad")将给出'cbac';开头的a和结尾的da被删除了。谢谢。 - scvalex
6
另外,这样可以以 任何顺序 删除字符:"site.ocm" > "site"。 - Eric O. Lebigot
8
@scvalex,哇哦,刚刚意识到在使用这种方法很久后它是很危险的,因为代码通常仍能正常工作。 - Flash
显示剩余4条评论
25个回答

857

strip并不意味着“删除此子字符串”。x.strip(y)y视为一组字符,并从x的两端剥离该集合中的任何字符。

Python 3.9及更高版本中,您可以使用removeprefixremovesuffix方法从字符串的任一侧删除整个子字符串:

url = 'abcdc.com'
url.removesuffix('.com')    # Returns 'abcdc'
url.removeprefix('abcdc.')  # Returns 'com'

相关的Python增强提案是PEP-616

Python 3.8及更早版本中,您可以使用endswith和切片:

url = 'abcdc.com'
if url.endswith('.com'):
    url = url[:-4]

或使用 正则表达式

import re
url = 'abcdc.com'
url = re.sub('\.com$', '', url)

4
我个人认为第一个例子使用endswith()测试会更好一些,而用正则表达式会带来一些性能损耗(解析正则表达式等)。我不会选择rsplit()的方法,但这是因为我不知道你确切想要实现什么。我猜你想要的是当且仅当.com出现在URL末尾时才删除它?如果你用rsplit解决方案处理像'www.commercialthingie.co.uk'这样的域名会遇到麻烦。 - Steef
13
url = url[:-4] if any(url.endswith(x) for x in ('.com','.net')) else url这行代码的意思是,如果URL以'.com'或'.net'结尾,则去掉URL中的最后四个字符,否则不做任何更改。 - Burhan Khalid
1
如果我写EXAMLPLE.COM,域名不区分大小写。(这是正则表达式解决方案的投票) - Jasen
3
这不是重新写过,rsplit() 的解决方案在原始字符串中间没有子字符串时,与 endswith() 的行为不同。例如:"www.comeandsee.com".rsplit(".com",1)[0] == "www.comeandsee",但是 "www.comeandsee.net".rsplit(".com",1)[0] == "www"。 - Steef
5
s[:-n]的语法有一个注意点:当n = 0时,它不会返回将字符串末尾的零个字符去掉后的字符串,而是返回空字符串。 - BlenderBender
显示剩余3条评论

111

如果你确定该字符串仅出现在末尾,则最简单的方法是使用 'replace':

url = 'abcdc.com'
print(url.replace('.com',''))

64
也会替换像 www.computerhope.com 这样的网址。使用 endswith() 进行检查,应该就可以了。 - ghostdog74
88
"www.computerhope.com".endswith(".com") 为真,但它仍然会出错! - user1974640
2
如果你确定字符串只出现在末尾,那么你的意思是“如果你确定子字符串只出现一次”吗?replace函数似乎也可以在字符串中间替换子字符串,但正如其他评论所建议的那样,它将替换子字符串的任何出现,为什么它应该在末尾我不理解。 - 463035818_is_not_a_number

72
def strip_end(text, suffix):
    if suffix and text.endswith(suffix):
        return text[:-len(suffix)]
    return text

@Boris 我之前喜欢它,没有额外检查后缀是否为空。 - yairchu
1
@yarichu 我复制了来自PEP 616的代码,该代码将此确切函数引入了stdlib。我认为这种方式更好的原因是,当你可以在Python中使用负索引时,必须执行len(text)-len(suffix)的原因不清楚(实际上,您在编辑中修复了该错误,并且曾经有一个错误的评论在此处告诉您不需要len(text),因此这似乎容易出错),而if suffix则清楚地说明了您实际检查的内容及其原因。 - user3064538

60

因为似乎还没有人指出这一点:

url = "www.example.com"
new_url = url[:url.rfind(".")]

使用这种方法比使用split()更高效,因为它不会创建新的列表对象,并且此解决方案适用于具有多个点的字符串。


哇,这是个不错的技巧。我无法让它失败,但我也很难想出它可能失败的方式。我喜欢它,但它非常“神奇”,仅凭看它很难知道它做了什么。我必须在头脑中逐个处理每一部分才能“理解它”。 - DevPlayer
23
如果要查找的字符串不存在,此方法将失败,并且错误地删除最后一个字符。 - robbat2

32

Python 3.9开始,您可以使用removesuffix替代:

'abcdc.com'.removesuffix('.com')
# 'abcdc'

Python代码可以在PEP 616中找到。 - Paul Tobias

28

取决于您了解URL的情况以及您要做什么。 如果您知道它将始终以“.com”(或“.net”或“.org”)结尾,则

 url=url[:-4]

如果只是想快速解决问题,那么这可能是最快的方法。如果涉及到更一般的URL,则最好研究Python附带的urlparse库。

另一方面,如果你只想从字符串中删除最后一个点号(.)以及之后的所有内容,那么……

url.rsplit('.',1)[0]

这将有效。或者如果你只想要第一个“.”之前的所有内容,可以尝试

url.split('.',1)[0]

17

如果你知道它是一个扩展程序,那么

url = 'abcdc.com'
...
url.rsplit('.', 1)[0]  # split at '.', starting from the right, maximum 1 split

这同样适用于 abcdc.comwww.abcdc.comabcdc.[任何内容],而且更具扩展性。


这对我来说似乎是最明显和最清晰的方式。但不必是扩展,你可以只在整个要匹配的子字符串上进行分割。 - Ben Farmer

15

在 Python 3.9+ 版本中:

text.removesuffix(suffix)

在任何 Python 版本中:

def remove_suffix(text, suffix):
    return text[:-len(suffix)] if text.endswith(suffix) and len(suffix) != 0 else text

或者使用一行代码:

remove_suffix = lambda text, suffix: text[:-len(suffix)] if text.endswith(suffix) and len(suffix) != 0 else text

1
或者 text[:-len(suffix)] if suffix and text.endswith(suffix) else text - user3064538

7

那么 url[:-4] 怎么样?


4
一旦遇到 .ca 或者 .co.uk 的网址,几乎肯定会导致 bug。 - Peter

6

声明:这种方法存在一个重大缺陷,即分区未锚定到URL的结尾,可能返回虚假结果。例如,URL“www.comcast.net”的结果为“www”(错误),而不是预期的“www.comcast.net”。因此,这个解决方案是有害的。除非您知道自己在做什么,否则不要使用它!

url.rpartition('.com')[0]

这很容易打出来,当url缺少后缀“.com”时,它也会正确地返回原始字符串(无错误)。


1
当只需要一个分割时,最好使用+1分区,因为它总是返回一个答案,不会出现IndexError。 - Gringo Suave
1
这段代码无法正确处理后缀不存在的情况。例如,对于 www.comcast.net,它将错误地返回 www - user3064538
1
这是一个非常出色的观点,@Boris!非常感谢你指出来。 - winni2k

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