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

时间:2009-06-24 14:44:01

标签: python string

我有以下代码:

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

我期待:abcdc

我得到了:abcd

现在我做

url.rsplit('.com', 1)

有更好的方法吗?

24 个答案:

答案 0 :(得分:452)

strip并不意味着“删除此子字符串”。 x.strip(y)y视为一组字符,并从x的末尾删除该字符集中的所有字符。

相反,您可以使用endswith并切片:

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

或使用正则表达式:

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

答案 1 :(得分:68)

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

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

答案 2 :(得分:37)

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

答案 3 :(得分:34)

因为似乎没有人指出这个问题:

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

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

答案 4 :(得分:22)

取决于您对网址的了解以及您正在尝试做的事情。如果您知道它将始终以'.com'(或'.net'或'.org')结尾,那么

 url=url[:-4]

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

如果你另一方面,你只想在最后''之后删除所有内容。然后在字符串中

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

会奏效。或者如果你想要一切都达到第一个'。'然后尝试

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

答案 5 :(得分:21)

Python 3.9开始,您可以改用removesuffix

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

答案 6 :(得分:10)

在一行中:

text if not text.endswith(suffix) or len(suffix) == 0 else text[:-len(suffix)]

答案 7 :(得分:8)

url[:-4]怎么样?

答案 8 :(得分:8)

如果您知道它是扩展名,那么

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

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

答案 9 :(得分:6)

对于网址(因为它似乎是给定示例的主题的一部分),可以做这样的事情:

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')

如果您只需要拆分“.com”或任何特定内容,也可以与str.endswith(suffix)结合使用。

答案 10 :(得分:3)

因为这是一个非常受欢迎的问题,所以我添加了另一个现在可用的解决方案。使用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[:]

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

  1. 少易碎: 该代码将不依赖用户来计算文字的长度。

  2. 绩效更高: 该代码不需要调用Python内置的len函数,也不需要调用更昂贵的str.replace()方法。

  3. 更具描述性: 与传统的字符串切片方法相比,这些方法为代码的可读性提供了更高级别的API。

答案 11 :(得分:3)

如果需要剥离某个字符串的某个末端(如果存在),否则什么也不做。我最好的解决方案。您可能会想使用前两个实现之一,但是为了完整起见,我包括了第三个实现。

对于常量后缀:

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中,即使re模​​块使用DFA编译正则表达式引擎,但对于大量调用或长字符串来说,几乎可以肯定的是regex变体会变慢,因为JIT会优化lambda的大部分开销。 / p>

但是在cPython中,您运行的regex的c代码几乎可以肯定比在所有情况下都胜过后缀集合版本的算法优势。

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

答案 12 :(得分:3)

假设您想删除域,无论它是什么(.com,.net等)。我建议找到.并从此删除所有内容。

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

在这里,我正在使用rfind来解决类似abcdc.com.net之类的网址的问题,该网址应简化为名称abcdc.com

如果您还担心www.,则应明确检查它们:

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

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

如果您的网址比该网址更野,请查看人们响应的正则表达式答案。

答案 13 :(得分:2)

  

url.rsplit(' .com',1)

不太对劲。

您实际需要写的是

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

,看起来很简洁恕我直言。

但是,我个人偏好是这个选项,因为它只使用一个参数:

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

答案 14 :(得分:1)

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

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   '

答案 15 :(得分:1)

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlMapperExtensions.TableNameMapper = TableNameMapper;
            var name = TableNameMapper(typeof(User));
        }

        private static string TableNameMapper(Type type)
        {
            dynamic tableattr = type.GetCustomAttributes(false).SingleOrDefault(attr => attr.GetType().Name == "TableAttribute");
            var name = string.Empty;

            if (tableattr != null)
            {
                name = tableattr.Name;
            }

            return name;
        }
    }

    [Table("tblUser")]
    public class User
    {
        public int Id { get; set; }
        public string Title { get; set; }
    }
}

我想重复这个答案是最有表现力的方式。当然,以下将占用更少的CPU时间

import re

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

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

什么时候CPU是瓶颈?在司机,也许。

使用正则表达式的优点是代码可重用性。如果您接下来要删除' .me' ,只有三个字符?

相同的代码可以解决问题。

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

答案 16 :(得分:0)

使用替换和计数

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

mystring = "www.comwww.com"

前缀:

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

后缀(你把前缀写反了).com变成moc.

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

答案 17 :(得分:0)

Python> = 3.9:

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

Python <3.9:

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

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

答案 18 :(得分:0)

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

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

答案 19 :(得分:0)

如果您的意思是只删除扩展程序

url = 'abcdc.com'
print('.'.join(url.split('.')[:-1]))

它适用于任何扩展,文件名中也存在潜在的其他点。它只是将字符串拆分为点上的列表并加入它而没有最后一个元素。

可能不是最快的,但对我而言,它比其他方法更具可读性。

答案 20 :(得分:0)

在我的情况下,我需要提出异常,所以我做了:

plot_ly(head(iris, 1), 
   x = ~Sepal.Length, y = ~Sepal.Width, color=~Species,      
   colors = setNames("#FF5748", "setosa"),
   type = "scatter", mode = "markers")

答案 21 :(得分:0)

def remove_file_type(infile):
import re
return(re.sub('\.[^.]*$','',infile))
remove_file_type('abc.efg')'abc'

答案 22 :(得分:0)

或者你可以使用split:

a = 'abccomputer.com'
res = a.split('.com',1)[0]

答案 23 :(得分:0)

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

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