如何从字符串的末尾删除子字符串?

我有以下代码:

url = 'abcdc.com'
print(url.strip('.com'))

我期望:abcdc

我得到:abcd

现在我知道了

url.rsplit('.com', 1)

有没有更好的办法?

957786 次浏览

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)

url[:-4]呢?

这是正则表达式的完美用法:

>>> import re
>>> re.match(r"(.*)\.com", "hello.com").group(1)
'hello'

如果你知道是分机,那么

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

这同样适用于abcdc.comwww.abcdc.comabcdc.[anything],并且更具可扩展性。

这取决于你对url的了解程度以及你想要做什么。如果你知道它总是以“。com”(或“。net”或“。org”)结尾,那么

 url=url[:-4]

是最快的解决办法。如果它是一个更通用的url,那么你可能会更好地查看python附带的urlparse库。

另一方面,如果你只是想在期末考试后删除所有内容。'在一个字符串中

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

将工作。或者如果你想把所有的东西都放在第一。那就试试

url.split('.',1)[0]
def strip_end(text, suffix):
if suffix and text.endswith(suffix):
return text[:-len(suffix)]
return text

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

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

在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

你可以使用split:

'abccomputer.com'.split('.com',1)[0]
# 'abccomputer'

对于url(通过给定的例子,它似乎是主题的一部分),可以这样做:

import os
url = 'http://www.stackoverflow.com'
name,ext = os.path.splitext(url)
print (name, ext)


#Or:
ext = '.'+url.split('.')[-1]
name = url[:-len(ext)]
print (name, ext)

都将输出: ('http://www.stackoverflow', '.com') < / p >

如果你只需要拆分“。com”或任何特定的东西,这也可以与str.endswith(suffix)组合。

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

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

这应该比使用split()的方法更有效,因为没有创建新的列表对象,并且此解决方案适用于带有几个点的字符串。

在我的情况下,我需要引发一个异常,所以我做了:

class UnableToStripEnd(Exception):
"""A Exception type to indicate that the suffix cannot be removed from the text."""


@staticmethod
def get_exception(text, suffix):
return UnableToStripEnd("Could not find suffix ({0}) on text: {1}."
.format(suffix, text))




def strip_end(text, suffix):
"""Removes the end of a string. Otherwise fails."""
if not text.endswith(suffix):
raise UnableToStripEnd.get_exception(text, suffix)
return text[:len(text)-len(suffix)]
import re


def rm_suffix(url = 'abcdc.com', suffix='\.com'):
return(re.sub(suffix+'$', '', url))

我想重复一下这个答案,作为最具表现力的回答。当然,以下操作会占用更少的CPU时间:

def rm_dotcom(url = 'abcdc.com'):
return(url[:-4] if url.endswith('.com') else url)

但是,如果CPU是瓶颈,为什么要用Python编写呢?

CPU什么时候会成为瓶颈?在驾驶方面,可能是这样。

使用正则表达式的优点是代码可重用性。如果你接下来想要移除。Me ',只有三个字?

同样的代码可以做到这一点:

>>> rm_sub('abcdc.me','.me')
'abcdc'

DSCLAIMER此方法有一个严重缺陷,即分区没有锚定到url的末尾,并可能返回虚假的结果。例如,URL &;www.comcast.net&;是“www"(不正确)而不是预期的&;www.comcast.net&;因此,这个解决方案是邪恶的。除非你知道你在做什么,否则不要使用它!

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

这很容易输入,并且在url中缺少后缀'.com'时正确地返回原始字符串(没有错误)。

如果你只想剥离扩展:

'.'.join('abcdc.com'.split('.')[:-1])
# 'abcdc'

它适用于任何扩展名,与潜在的其他点存在的文件名以及。它只是将字符串拆分为一个点列表,并在没有最后一个元素的情况下将其连接起来。

这里,我有一个最简单的代码。

url=url.split(".")[0]

假设你想删除域名,不管它是什么(.com, .net等)。我建议找到.并删除从那一点开始的所有东西。

url = 'abcdc.com'
dot_index = url.rfind('.')
url = url[:dot_index]

在这里,我使用rfind来解决像abcdc.com.net这样的url的问题,它应该被简化为名字abcdc.com

如果你也关心__abc,你应该显式检查它们:

if url.startswith("www."):
url = url.replace("www.","", 1)

替换中的1用于奇怪的边例,如www.net.www.com

如果你的url比这更乱,看看人们用正则表达式回答的问题。

如果你需要剥离字符串的某一端,如果它存在,否则什么都不做。我最好的解决方案。您可能会想使用前两个实现中的一个,但是为了完整性,我已经包括了第三个实现。

对于常量后缀:

def remove_suffix(v, s):
return v[:-len(s)] if v.endswith(s) else v
remove_suffix("abc.com", ".com") == 'abc'
remove_suffix("abc", ".com") == 'abc'

对于正则表达式:

def remove_suffix_compile(suffix_pattern):
r = re.compile(f"(.*?)({suffix_pattern})?$")
return lambda v: r.match(v)[1]
remove_domain = remove_suffix_compile(r"\.[a-zA-Z0-9]{3,}")
remove_domain("abc.com") == "abc"
remove_domain("sub.abc.net") == "sub.abc"
remove_domain("abc.") == "abc."
remove_domain("abc") == "abc"

对于常量后缀的集合,对于大量调用的渐近最快的方法:

def remove_suffix_preprocess(*suffixes):
suffixes = set(suffixes)
try:
suffixes.remove('')
except KeyError:
pass


def helper(suffixes, pos):
if len(suffixes) == 1:
suf = suffixes[0]
l = -len(suf)
ls = slice(0, l)
return lambda v: v[ls] if v.endswith(suf) else v
si = iter(suffixes)
ml = len(next(si))
exact = False
for suf in si:
l = len(suf)
if -l == pos:
exact = True
else:
ml = min(len(suf), ml)
ml = -ml
suffix_dict = {}
for suf in suffixes:
sub = suf[ml:pos]
if sub in suffix_dict:
suffix_dict[sub].append(suf)
else:
suffix_dict[sub] = [suf]
if exact:
del suffix_dict['']
for key in suffix_dict:
suffix_dict[key] = helper([s[:pos] for s in suffix_dict[key]], None)
return lambda v: suffix_dict.get(v[ml:pos], lambda v: v)(v[:pos])
else:
for key in suffix_dict:
suffix_dict[key] = helper(suffix_dict[key], ml)
return lambda v: suffix_dict.get(v[ml:pos], lambda v: v)(v)
return helper(tuple(suffixes), None)
domain_remove = remove_suffix_preprocess(".com", ".net", ".edu", ".uk", '.tv', '.co.uk', '.org.uk')

最后一个在pypy中可能比在cpython中快得多。对于几乎所有不涉及大量潜在后缀字典的情况(至少在cPython中无法轻松表示为regex), regex变体可能比这个更快。

在PyPy中,regex变体对于大量调用或长字符串几乎肯定更慢,即使re模块使用DFA编译regex引擎,因为lambda的绝大多数开销将由JIT优化。

然而,在cPython中,在几乎所有情况下,你为正则表达式运行的c代码的比较几乎肯定超过了后缀集合版本的算法优势。

编辑:https://m.xkcd.com/859/

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

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

我使用内置的rstrip函数来完成如下操作:

string = "test.com"
suffix = ".com"
newstring = string.rstrip(suffix)
print(newstring)
test

Python >= 3.9:

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

Python & lt;3.9:

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


remove_suffix('abcdc.com', '.com')

一个更广泛的解决方案,将可能性添加到替换后缀(可以通过替换为空字符串来删除)和设置最大替换数:

def replacesuffix(s,old,new='',limit=1):
"""
String suffix replace; if the string ends with the suffix given by parameter `old`, such suffix is replaced with the string given by parameter `new`. The number of replacements is limited by parameter `limit`, unless `limit` is negative (meaning no limit).


:param s: the input string
:param old: the suffix to be replaced
:param new: the replacement string. Default value the empty string (suffix is removed without replacement).
:param limit: the maximum number of replacements allowed. Default value 1.
:returns: the input string with a certain number (depending on parameter `limit`) of the rightmost occurrences of string given by parameter `old` replaced by string given by parameter `new`
"""
if s[len(s)-len(old):] == old and limit != 0:
return replacesuffix(s[:len(s)-len(old)],old,new,limit-1) + new
else:
return s

在您的情况下,给定默认参数,将获得所需的结果:

replacesuffix('abcdc.com','.com')
>>> 'abcdc'

一些更普遍的例子:

replacesuffix('whatever-qweqweqwe','qwe','N',2)
>>> 'whatever-qweNN'


replacesuffix('whatever-qweqweqwe','qwe','N',-1)
>>> 'whatever-NNN'


replacesuffix('12.53000','0',' ',-1)
>>> '12.53   '

因为这是一个非常受欢迎的问题,我添加了另一个现在可用的解决方案。在python 3.9 (https://docs.python.org/3.9/whatsnew/3.9.html)中,函数removesuffix()将被添加(和removeprefix()),这个函数正是这里所质疑的。

url = 'abcdc.com'
print(url.removesuffix('.com'))

输出:

'abcdc'

PEP 616 (https://www.python.org/dev/peps/pep-0616/)显示了它如何的行为(它不是真正的实现):

def removeprefix(self: str, prefix: str, /) -> str:
if self.startswith(prefix):
return self[len(prefix):]
else:
return self[:]

以及它对自实现解决方案的好处:

    <李> < p > 不那么脆弱: 代码将不依赖于用户来计算文字的长度 <李> < p > 更好的性能: 该代码不需要调用Python内置的len函数,也不需要调用更昂贵的str.replace()方法 <李> < p > 更具描述性的: 与传统的字符串切片方法相比,这些方法为代码可读性提供了更高级别的API

使用replace和count

这可能看起来有点hack,但它确保你在不使用startswith和if语句的情况下进行安全替换,使用replace的count参数你可以将替换限制为一个:

mystring = "www.comwww.com"

前缀:

print(mystring.replace("www.","",1))

后缀.com变成了moc.:

print(mystring[::-1].replace("moc.","",1)[::-1])