如何从字符串末尾删除子字符串(删除字符串的后缀)?
- 2024-12-17 08:30:00
- admin 原创
- 140
问题描述:
我有以下代码:
url = 'abcdc.com'
print(url.strip('.com'))
我预期:abcdc
我得到:abcd
现在我明白了
url.rsplit('.com', 1)
有没有更好的方法?
请参阅.strip/.rstrip/.lstrip 字符串方法在 Python 中如何工作?以获得有关第一次尝试的具体解释。
解决方案 1:
strip
并不意味着“删除这个子字符串”。x.strip(y)
将其y
视为一组字符,并从 的两端删除该集合中的任何字符x
。
在Python 3.9 及更新版本中,您可以使用removeprefix
andremovesuffix
方法从字符串的两侧删除整个子字符串:
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)
解决方案 2:
如果您确定该字符串只出现在末尾,那么最简单的方法是使用“replace”:
url = 'abcdc.com'
print(url.replace('.com',''))
解决方案 3:
def strip_end(text, suffix):
if suffix and text.endswith(suffix):
return text[:-len(suffix)]
return text
解决方案 4:
因为似乎还没有人指出这一点:
url = "www.example.com"
new_url = url[:url.rfind(".")]
这应该比使用的方法更有效,split()
因为没有创建新的列表对象,并且此解决方案适用于具有多个点的字符串。
解决方案 5:
从 开始Python 3.9
,你可以使用removesuffix
:
'abcdc.com'.removesuffix('.com')
# 'abcdc'
解决方案 6:
取决于您对 URL 的了解程度以及您具体要做什么。如果您知道它总是以 '.com'(或 '.net' 或 '.org')结尾,那么
url=url[:-4]
是最快的解决方案。如果是更通用的 URL,那么最好查看 python 附带的 urlparse 库。
另一方面,如果你只是想删除字符串中最后一个“。”之后的所有内容,那么
url.rsplit('.',1)[0]
可以。或者,如果您只想获取第一个“.”之前的所有内容,请尝试
url.split('.',1)[0]
解决方案 7:
在 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
解决方案 8:
如果你知道这是一个扩展,那么
url = 'abcdc.com'
...
url.rsplit('.', 1)[0] # split at '.', starting from the right, maximum 1 split
abcdc.com
这与或www.abcdc.com
或同样有效,abcdc.[anything]
并且更具可扩展性。
解决方案 9:
怎么样url[:-4]
?
解决方案 10:
对于 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')
str.endswith(suffix)
如果您只需要拆分“.com”或任何特定内容,也可以将其与此相结合。
解决方案 11:
免责声明此方法存在严重缺陷,即分区未锚定到 URL 末尾,可能会返回虚假结果。例如,URL“www.comcast.net”的结果为“www”(不正确),而不是预期的“www.comcast.net”。因此,此解决方案是邪恶的。除非您知道自己在做什么,否则请勿使用它!
url.rpartition('.com')[0]
这很容易输入,并且当缺少后缀“.com”时也能正确返回原始字符串(无错误)url
。
解决方案 12:
假设您想删除域名,无论它是什么(.com、.net 等)。我建议找到.
并从该点开始删除所有内容。
url = 'abcdc.com'
dot_index = url.rfind('.')
url = url[:dot_index]
这里我使用来解决像这样的 URL 应该简化为名称rfind
的问题。abcdc.com.net
`abcdc.com`
如果您还关心www.
s,您应该明确检查它们:
if url.startswith("www."):
url = url.replace("www.","", 1)
replace 中的 1 适用于奇怪的边缘情况,例如www.net.www.com
如果您的 url 比这更狂野,请查看人们响应的正则表达式答案。
解决方案 13:
如果您只想删除扩展名:
'.'.join('abcdc.com'.split('.')[:-1])
# 'abcdc'
它适用于任何扩展名,文件名中也可能存在其他点。它只是将字符串拆分为点列表,然后将其连接起来,但不包含最后一个元素。
解决方案 14:
如果您需要删除字符串的某个结尾(如果存在),否则什么也不做。我最好的解决方案。您可能想要使用前两种实现中的一种,但为了完整性,我已包括了第三种实现。
对于常量后缀:
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 中无法轻易表示为正则表达式)的情况下,正则表达式变体可能比这个更快。
在 PyPy 中,即使 re 模块使用 DFA 编译正则表达式引擎,正则表达式变体对于大量调用或长字符串也几乎肯定会更慢,因为 lambda 的绝大多数开销将被 JIT 优化掉。
然而在 cPython 中,运行正则表达式比较的 c 代码的事实几乎在所有情况下都肯定超过了后缀集合版本的算法优势。
编辑:https ://m.xkcd.com/859/
解决方案 15:
由于这是一个非常常见的问题,因此我添加了另一个现在可用的解决方案。使用 python 3.9(https://docs.python.org/3.9/whatsnew/3.9.htmlremovesuffix()
),将添加该函数(和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[:]
与自行实施的解决方案相比,它有哪些优势:
不太脆弱:代码将不再依赖用户来计算文字的长度。
性能更佳:代码不需要调用 Python 内置的 len 函数或更昂贵的 str.replace() 方法。
更具描述性:与传统的字符串切片方法相比,这些方法提供了更高级别的 API,以提高代码可读性。
解决方案 16:
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'
解决方案 17:
就我而言,我需要引发异常,因此我这样做了:
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)]
解决方案 18:
您可以使用分割:
'abccomputer.com'.split('.com',1)[0]
# 'abccomputer'
解决方案 19:
更广泛的解决方案,增加了替换后缀的可能性(您可以通过用空字符串替换来删除)并设置最大替换次数:
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 '
解决方案 20:
Python 3.8 中的删除后缀的函数:
def removesuffix(text, suffix):
if text.endswith(suffix):
return text[:-len(suffix)]
else:
return text
解决方案 21:
这是正则表达式的完美用法:
>>> import re
>>> re.match(r"(.*).com", "hello.com").group(1)
'hello'
解决方案 22:
使用 Mozilla 托管的公共后缀列表。它可作为tldextract
Python 库使用。
import tldextract
url = 'abcdc.com'
# Extract the domain and TLD
extracted = tldextract.extract(url)
domain, tld = extracted.domain, extracted.suffix
if tld and tld != 'localhost':
url_without_tld = domain
else:
url_without_tld = url
print(url_without_tld)
解决方案 23:
这里,我有一个最简单的代码。
url=url.split(".")[0]
解决方案 24:
使用替换和计数
这可能看起来有点像黑客,但它可以确保你无需使用startswith
if 语句就可以安全替换,使用count
replace 的参数你可以将替换限制为一个:
mystring = "www.comwww.com"
前缀:
print(mystring.replace("www.","",1))
后缀(将前缀反过来写).com
变成moc.
:
print(mystring[::-1].replace("moc.","",1)[::-1])
解决方案 25:
我使用内置的rstrip函数来执行此操作,如下所示:
string = "test.com"
suffix = ".com"
newstring = string.rstrip(suffix)
print(newstring)
test