Wie entferne ich einen Teilstring vom Ende eines Strings in Python?


382

Ich habe folgenden Code:

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

Ich erwartete: abcdc

Ich habe: abcd

Jetzt mache ich

url.rsplit('.com', 1)

Gibt es einen besseren Weg?


6
Strip entfernt die Zeichen, die an beiden Enden der Zeichenfolge angegeben sind. In Ihrem Fall werden ".", "c", "o" und "m" entfernt.
Truppo

6
Außerdem werden diese Zeichen von der Vorderseite der Zeichenfolge entfernt. Wenn Sie nur möchten, dass es vom Ende entfernt wird, verwenden Sie rstrip ()
Andre Miller

42
Ja. str.strip macht nicht das, was du denkst. str.strip entfernt alle angegebenen Zeichen am Anfang und am Ende der Zeichenfolge. "Acbacda" .strip ("ad") ergibt also "cbac"; Das a am Anfang und das da am Ende wurden entfernt. Prost.
Scvalex

2
Außerdem werden die Zeichen in beliebiger Reihenfolge entfernt : "site.ocm"> "site".
Eric O Lebigot

1
@scvalex, wow, habe gerade gemerkt, dass dies schon seit Ewigkeiten so verwendet wird - es ist gefährlich, weil der Code sowieso oft funktioniert
Flash

Antworten:


556

strip bedeutet nicht "diesen Teilstring entfernen". x.strip(y)behandelt yals Zeichensatz und entfernt alle Zeichen in diesem Satz von den Enden von x.

Stattdessen könnten Sie verwenden endswith und schneiden:

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

Oder mit regulären Ausdrücken :

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

4
Ja, ich selbst denke, dass das erste Beispiel mit dem Test endwith () das bessere wäre. Die Regex-Version würde einige Leistungseinbußen nach sich ziehen (Analyse der Regex-Datei usw.). Ich würde nicht mit rsplit () arbeiten, aber das liegt daran, dass ich nicht weiß, was Sie genau erreichen wollen. Ich denke, es entfernt das .com genau dann, wenn es am Ende der URL erscheint? Die rsplit-Lösung würde Ihnen Probleme bereiten, wenn Sie sie für Domain-Namen wie 'www.commercialthingie.co.uk'
Steef

13
url = url[:-4] if any(url.endswith(x) for x in ('.com','.net')) else url
Burhan Khalid

1
Was ist, wenn ich EXAMLPLE.COMDomain-Namen schreibe , bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird? (Dies ist eine Abstimmung für die Regex-Lösung)
Jasen

3
Es ist kein Umschreiben, die rsplit()Lösung hat nicht das gleiche Verhalten wie die endswith(), wenn die ursprüngliche Zeichenfolge nicht den Teilstring am Ende hat, sondern irgendwo in der Mitte. Zum Beispiel: "www.comeandsee.com".rsplit(".com",1)[0] == "www.comeandsee"aber"www.comeandsee.net".rsplit(".com",1)[0] == "www"
Steef

1
Die Syntax s[:-n]hat eine Einschränkung: Denn n = 0dies gibt nicht die Zeichenfolge mit den letzten abgeschnittenen Nullzeichen zurück, sondern die leere Zeichenfolge.
BlenderBender

90

Wenn Sie sicher sind, dass die Zeichenfolge nur am Ende angezeigt wird, ist es am einfachsten, 'replace' zu verwenden:

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

56
das wird auch url wie ersetzen www.computerhope.com. mach einen Check mit endswith()und sollte in Ordnung sein.
Ghostdog74

72
"www.computerhope.com".endswith(".com")ist wahr, es wird immer noch brechen!

1
"Wenn Sie sicher sind, dass die Zeichenfolge nur am Ende angezeigt wird", meinen Sie "Wenn Sie sicher sind, dass die Teilzeichenfolge nur einmal angezeigt wird"? Ersetzen scheint auch zu funktionieren, wenn sich der Teilstring in der Mitte befindet, aber wie der andere Kommentar andeutet, wird er jedes Auftreten des Teilstrings ersetzen, warum es am Ende sein sollte, verstehe ich nicht
idclev 463035818

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

4
Wenn Sie wissen, dass das Suffix nicht leer ist (wie wenn es eine Konstante ist), dann: Rückgabetext [: - len (Suffix)]
MarcH

4
Vielen Dank. Die letzte Zeile könnte gekürzt werden:return text[:-len(suffix)]
Jabba

3
@Jabba: Leider funktioniert das bei leeren Suffixen nicht, wie fuenfundachtzig erwähnt hat.
Yairchu

46

Da es so aussieht, als hätte noch niemand darauf hingewiesen:

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

Dies sollte effizienter sein als die verwendeten Methoden, split()da kein neues Listenobjekt erstellt wird. Diese Lösung funktioniert für Zeichenfolgen mit mehreren Punkten.


Wow das ist ein schöner Trick. Ich konnte dies nicht zum Scheitern bringen, aber es fiel mir auch schwer, mir Möglichkeiten auszudenken, wie dies fehlschlagen könnte. Ich mag es, aber es ist sehr "magisch", schwer zu wissen, was dies bewirkt, wenn man es nur ansieht. Ich musste jeden Teil der Linie mental verarbeiten, um "es zu bekommen".
DevPlayer

14
Dies schlägt fehl, wenn die gesuchte Zeichenfolge NICHT vorhanden ist und stattdessen fälschlicherweise das letzte Zeichen entfernt wird.
Robbat2

25

Hängt davon ab, was Sie über Ihre URL wissen und was Sie genau versuchen. Wenn Sie wissen, dass es immer mit '.com' (oder '.net' oder '.org') endet, dann

 url=url[:-4]

ist die schnellste Lösung. Wenn es sich um allgemeinere URLs handelt, ist es wahrscheinlich besser, in die mit Python gelieferte URL-Bibliothek zu schauen.

Wenn Sie andererseits einfach alles nach dem letzten '.' Entfernen möchten. in einer Zeichenfolge dann

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

wird funktionieren. Oder wenn Sie wollen, wollen Sie einfach alles bis zum ersten '.' dann versuche es

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

16

Wenn Sie wissen, dass es sich um eine Erweiterung handelt, dann

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

Dies funktioniert genauso gut mit abcdc.comoder www.abcdc.comoder abcdc.[anything]und ist erweiterbarer.


12

In einer Zeile:

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


7

Für URLs (da es im angegebenen Beispiel ein Teil des Themas zu sein scheint) kann man Folgendes tun:

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)

Beide geben Folgendes aus: ('http://www.stackoverflow', '.com')

Dies kann auch kombiniert werden, str.endswith(suffix)wenn Sie nur ".com" oder etwas Bestimmtes teilen müssen.


5

url.rsplit ('. com', 1)

ist nicht ganz richtig.

Was Sie tatsächlich schreiben müssten, ist

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

und es sieht meiner Meinung nach ziemlich prägnant aus.

Meine persönliche Präferenz ist jedoch diese Option, da nur ein Parameter verwendet wird:

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

1
+1 Partition wird bevorzugt, wenn nur eine Aufteilung erforderlich ist, da immer eine Antwort zurückgegeben wird und kein IndexError auftritt.
Gringo Suave


2

Wenn Sie ein Ende eines Strings entfernen müssen, falls vorhanden, tun Sie nichts. Meine besten Lösungen. Sie werden wahrscheinlich eine der ersten beiden Implementierungen verwenden wollen, der Vollständigkeit halber habe ich jedoch die dritte aufgenommen.

Für ein konstantes Suffix:

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'

Für eine Regex:

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"

Für eine Sammlung konstanter Suffixe der asymptotisch schnellste Weg für eine große Anzahl von Anrufen:

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

Der letzte ist bei Pypy wahrscheinlich deutlich schneller als bei Cpython. Die Regex-Variante ist wahrscheinlich in praktisch allen Fällen schneller, in denen keine großen Wörterbücher mit potenziellen Suffixen enthalten sind, die zumindest in cPython nicht einfach als Regex dargestellt werden können.

In PyPy ist die Regex-Variante für eine große Anzahl von Aufrufen oder langen Zeichenfolgen mit ziemlicher Sicherheit langsamer, selbst wenn das Re-Modul eine DFA-kompilierende Regex-Engine verwendet, da der überwiegende Teil des Overheads der Lambdas von der JIT optimiert wird.

In cPython jedoch vergleicht die Tatsache, dass Ihr laufender c-Code für den regulären Ausdruck mit ziemlicher Sicherheit die algorithmischen Vorteile der Suffix-Auflistungsversion in fast allen Fällen.


2

Wenn Sie nur die Erweiterung entfernen möchten:

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

Es funktioniert mit jeder Erweiterung, wobei potenzielle andere Punkte auch im Dateinamen vorhanden sind. Es teilt die Zeichenfolge einfach als Liste auf Punkte und verbindet sie ohne das letzte Element.


2
import re

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

Ich möchte diese Antwort als den ausdrucksstärksten Weg wiederholen. Folgendes würde natürlich weniger CPU-Zeit in Anspruch nehmen:

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

Wenn jedoch die CPU der Flaschenhals ist, warum in Python schreiben?

Wann ist CPU überhaupt ein Flaschenhals? Vielleicht bei Fahrern.

Die Vorteile der Verwendung von regulären Ausdrücken liegen in der Wiederverwendbarkeit von Code. Was ist, wenn Sie als nächstes '.me' entfernen möchten, das nur drei Zeichen enthält?

Der gleiche Code würde den Trick machen:

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

1

In meinem Fall musste ich eine Ausnahme auslösen, also tat ich Folgendes:

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

Angenommen, Sie möchten die Domain entfernen, unabhängig davon, um was es sich handelt (.com, .net usw.). Ich empfehle, das zu finden .und alles von diesem Punkt an zu entfernen.

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

Hier verwende ich rfind, um das Problem von URLs zu lösen, die abcdc.com.netauf den Namen reduziert werden sollten abcdc.com.

Wenn Sie auch über www.s besorgt sind , sollten Sie explizit nach ihnen suchen:

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

Die 1 in Ersetzen ist für seltsame Randfälle wie www.net.www.com

Wenn Ihre URL wilder wird, sehen Sie sich die Regex-Antworten an, mit denen die Leute geantwortet haben.


1

Ich habe die eingebaute rstrip- Funktion verwendet, um Folgendes zu tun:

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

Schlechte Idee. Versuchen Sie es "test.ccom".
Shital Shah

Dies ist jedoch nicht der Punkt der Frage. Es wurde nur gebeten, einen bekannten Teilstring vom Ende eines anderen zu entfernen. Dies funktioniert genau wie erwartet.
Alex

1

Sie können split verwenden:

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

5
Wenn a = 'www.computerbugs.com'dies mit 'www'
yairchu

0

Dies ist eine perfekte Verwendung für reguläre Ausdrücke:

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

5
Sie sollten auch ein $ hinzufügen, um sicherzustellen, dass Sie mit Hostnamen übereinstimmen, die auf ".com" enden .
Cristian Ciupitu

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

1
Ihre Antwort für Python 3.9 ist ein Duplikat dieser Antwort oben. Ihre Antwort für frühere Versionen wurde auch in diesem Thread oft beantwortet und würde nichts zurückgeben, wenn die Zeichenfolge nicht das Suffix hat.
Xavier Guihot
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.