Как удалить подстроку из конца строки в Python?

383

У меня есть следующий код:

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

Я ожидал: abcdc

Я получил: abcd

Сейчас делаю

url.rsplit('.com', 1)

Есть ли способ лучше?

Ramya
источник
6
strip удаляет символы, заданные с обоих концов строки, в вашем случае она удаляет ".", "c", "o" и "m".
Truppo
6
Он также удалит эти символы с начала строки. Если вы просто хотите, чтобы его удалили с конца, используйте rstrip ()
Andre Miller
42
Да. str.strip не делает то, что вы думаете. str.strip удаляет любой из символов, указанных в начале и конце строки. Итак, «acbacda» .strip («ad») дает «cbac»; А в начале и да в конце были раздеты. Приветствия.
Scvalex
2
Плюс, это удаляет символы в любом порядке : "site.ocm"> "site".
Эрик О Лебиго
1
@scvalex, вау, только что понял это, использовав его таким образом целую вечность - это опасно, потому что код часто работает так или иначе
Flash

Ответы:

557

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)
Steef
источник
4
Да, я сам думаю, что первый пример с тестом endwith () был бы лучшим; регулярное выражение может повлечь за собой некоторое снижение производительности (разбор регулярного выражения и т. д.). Я бы не стал использовать 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
Бурхан Халид
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
1
Синтаксис s[:-n]имеет предостережение: для n = 0, это не возвращает строку с обрезанными последними нулевыми символами, но вместо этого пустую строку.
BlenderBender
90

Если вы уверены, что строка появляется только в конце, то самый простой способ - использовать «заменить»:

url = 'abcdc.com'
print(url.replace('.com',''))
Чарльз Коллис
источник
56
это также заменит URL как www.computerhope.com. сделать проверку с endswith()и должно быть в порядке.
ghostdog74
72
"www.computerhope.com".endswith(".com")это правда, все равно сломается!
1
«Если вы уверены, что строка появляется только в конце», вы имеете в виду «Если вы уверены, что подстрока появляется только один раз»? Кажется, что замена также работает, когда подстрока находится посередине, но, как предполагает другой комментарий, она заменит любое вхождение подстроки, почему это должно быть в конце, я не понимаю
idclev 463035818
49
def strip_end(text, suffix):
    if not text.endswith(suffix):
        return text
    return text[:len(text)-len(suffix)]
yairchu
источник
4
Если вы знаете, что суффикс не пустой (например, когда он является константой), тогда: верните текст [: - len (суффикс)]
MarcH
4
Спасибо. Последняя строка может быть сокращена:return text[:-len(suffix)]
Джабба
3
@Jabba: К сожалению, это не сработает для пустых суффиксов, как упомянул fuenfundachtzig.
Яирчу
46

Поскольку кажется, что никто еще не указал на это:

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

Это должно быть более эффективным, чем методы, использующие, split()поскольку новый объект списка не создается, и это решение работает для строк с несколькими точками.

user3129181
источник
Вау, это хороший трюк. Я не мог заставить это потерпеть неудачу, но мне также было трудно думать, как это может потерпеть неудачу. Мне нравится это, но это очень "волшебно", трудно понять, что это делает, просто глядя на это. Я должен был мысленно обработать каждую часть строки, чтобы «получить это».
DevPlayer
14
Это не работает, если искомая строка НЕ ​​присутствует, и вместо этого неправильно удаляет последний символ.
robbat2
25

Зависит от того, что вы знаете о своем URL и что именно вы пытаетесь сделать. Если вы знаете, что он всегда будет заканчиваться на «.com» (или «.net» или «.org»), тогда

 url=url[:-4]

это самое быстрое решение. Если это более общие URL-адреса, то вам, вероятно, лучше заглянуть в библиотеку urlparse, которая поставляется с python.

Если вы, с другой стороны, вы просто хотите удалить все после финального '.' в строке тогда

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

будет работать. Или, если вы хотите, просто хотите, чтобы все до первого ». тогда попробуй

url.split('.',1)[0]
dagw
источник
16

Если вы знаете, что это расширение, то

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

Это работает одинаково хорошо с abcdc.comили www.abcdc.comили abcdc.[anything]и является более расширяемым.

JohnMetta
источник
12

В одну строку:

text if not text.endswith(suffix) or len(suffix) == 0 else text[:-len(suffix)]
Дэвид Фостер
источник
8

Как насчет url[:-4]?

Дарен Томас
источник
Кажется, почти гарантированно приведет к ошибке, как только вы попали в .caили .co.ukURL.
Питер
7

Для 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» или что-то конкретное.

JHolta
источник
5

url.rsplit ('. com', 1)

не совсем верно.

Что вам на самом деле нужно написать

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

И выглядит ИМХО довольно лаконично

Тем не менее, я предпочитаю эту опцию, потому что она использует только один параметр:

url.rpartition('.com')[0]
winni2k
источник
1
Разделение +1 предпочтительнее, когда требуется только одно разбиение, поскольку оно всегда возвращает ответ, ошибка IndexError не возникает.
Gringo Suave
4

Начиная с Python 3.9, вы можете использовать removesuffixвместо:

'abcdc.com'.removesuffix('.com')
# 'abcdc'
Ксавье Гихот
источник
2

Если вам нужно удалить какой-то конец строки, если она существует, иначе ничего не делайте. Мои лучшие решения. Вы, вероятно, захотите использовать одну из первых двух реализаций, однако я включил третью для полноты.

Для постоянного суффикса:

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 для компиляции, поскольку JIT оптимизирует подавляющее большинство служебных данных лямбды.

В cPython, однако, тот факт, что ваш выполняющийся код c для регулярных выражений почти наверняка сравнивает алгоритмические преимущества версии коллекции суффиксов почти во всех случаях.

user1424589
источник
2

Вы можете использовать сплит:

'abccomputer.com'.split('.com',1)[0]
# 'abccomputer'
Лукас
источник
5
Когда a = 'www.computerbugs.com'это 'www
закончится
2

Если вы хотите удалить только расширение:

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

Это работает с любым расширением, с потенциальными другими точками, существующими также в имени файла. Он просто разбивает строку в виде списка по точкам и объединяет ее без последнего элемента.

DCs
источник
2
import re

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

Я хочу повторить этот ответ как самый выразительный способ сделать это. Конечно, следующее займет меньше процессорного времени:

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

Однако, если процессор является узким местом, зачем писать на Python?

Во всяком случае, когда CPU - это горлышко бутылки? В драйверах, может быть.

Преимущество использования регулярных выражений заключается в возможности повторного использования кода. Что если в следующий раз вы захотите удалить «.me», в котором всего три символа?

Тот же код сделает свое дело:

>>> rm_sub('abcdc.me','.me')
'abcdc'
user1854182
источник
1

В моем случае мне нужно было вызвать исключение, поэтому я сделал:

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)]
Хуан Исаза
источник
1

Здесь у меня есть самый простой код.

url=url.split(".")[0]
Аншуман Джаяпракаш
источник
1

Предполагая, что вы хотите удалить домен, независимо от того, что это (.com, .net и т. Д.). Я рекомендую найти .и удалить все с этого момента.

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

Здесь я использую, rfindчтобы решить проблему URL-адресов, abcdc.com.netкоторые должны быть сокращены до имени abcdc.com.

Если вы также беспокоитесь о www.s, вы должны явно проверить их:

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

1 в замене для странных крайних случаев, таких как www.net.www.com

Если ваш URL-адрес становится еще более диким, посмотрите на ответы регулярных выражений, на которые люди ответили.

Ксавье Гуай
источник
1

Я использовал встроенную функцию rstrip, чтобы сделать это следующим образом:

string = "test.com"
suffix = ".com"
newstring = string.rstrip(suffix)
print(newstring)
test
Alex
источник
Плохая идея. Попробуй "test.ccom".
Шиталь Шах
Но это не главное. Просто попросили удалить известную подстроку с конца другой. Это работает точно так, как ожидалось.
Алекс
0

Это идеальное использование для регулярных выражений:

>>> import re
>>> re.match(r"(.*)\.com", "hello.com").group(1)
'hello'
Аарон Маенпаа
источник
5
Вы также должны добавить $, чтобы убедиться, что вы соответствуете именам хостов, оканчивающимся на «.com».
Кристиан Чиупиту
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')
бесконечность
источник
2
Ваш ответ для Python 3.9 является дубликатом этого ответа выше. На ваш ответ за предыдущие версии также много раз отвечали в этой теме, и он ничего не даст, если строка не имеет суффикса.
Ксавье Гихот