ฉันจะลบสตริงย่อยออกจากจุดสิ้นสุดของสตริงใน Python ได้อย่างไร


382

ฉันมีรหัสต่อไปนี้:

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

ฉันคาดหวัง: abcdc

ฉันได้: abcd

ตอนนี้ฉันทำ

url.rsplit('.com', 1)

มีวิธีที่ดีกว่า?


6
ดึงแถบอักขระที่กำหนดจากปลายทั้งสองของสตริงในกรณีของคุณจะตัดแถบ ".", "c", "o" และ "m"
truppo

6
มันจะลบอักขระเหล่านั้นออกจากด้านหน้าของสตริง หากคุณเพียงแค่ต้องการให้ลบออกจากท้ายที่สุดการใช้ rstrip ()
อังเดรมิลเลอร์

42
ใช่. str.strip ไม่ได้ทำในสิ่งที่คุณคิด str.strip ลบอักขระใด ๆ ที่ระบุจากจุดเริ่มต้นและจุดสิ้นสุดของสตริง ดังนั้น "acbacda" .strip ("ad") จะให้ 'cbac'; ที่จุดเริ่มต้นและดาที่สิ้นสุดถูกปล้น ไชโย
scvalex

2
นอกจากนี้จะลบอักขระตามลำดับ : "site.ocm"> "site"
Eric O Lebigot

1
@scvalex ว้าวเพิ่งรู้ตัวว่ามันใช้วิธีนี้มานานแล้ว - มันอันตรายเพราะโค้ดมักจะเกิดขึ้นเพื่อทำงานต่อไป
Flash

คำตอบ:


556

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)

4
ใช่ฉันเองคิดว่าตัวอย่างแรกด้วยการทดสอบ endswith () จะดีกว่า regex หนึ่งจะเกี่ยวข้องกับการลงโทษประสิทธิภาพบางอย่าง (แยกวิเคราะห์ regex ฯลฯ ) ฉันจะไม่ไปกับ 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
Burhan Khalid

1
ถ้าฉันเขียนEXAMLPLE.COMชื่อโดเมนไม่ต้องตรงตามตัวพิมพ์ใหญ่ - เล็ก (นี่คือคะแนนสำหรับโซลูชัน regex)
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

หากคุณแน่ใจว่าสตริงปรากฏขึ้นในตอนท้ายวิธีที่ง่ายที่สุดคือใช้ 'replace':

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

56
ที่จะแทนที่ URL เช่นwww.computerhope.comกัน ตรวจสอบด้วยendswith()และควรจะปรับ
ghostdog74

72
"www.computerhope.com".endswith(".com")เป็นจริงมันจะยังคงแตก!

1
"ถ้าคุณแน่ใจว่าสตริงปรากฏขึ้นที่ท้าย" คุณหมายถึง "ถ้าคุณแน่ใจว่าสตริงย่อยจะปรากฏเพียงครั้งเดียว"? แทนที่ดูเหมือนว่าจะทำงานด้วยเมื่อ substring อยู่ตรงกลาง แต่เป็นความคิดเห็นอื่นแสดงให้เห็นว่ามันจะมาแทนที่การเกิดขึ้นของ substring ทำไมมันควรจะเป็นที่สิ้นสุดฉันไม่เข้าใจ
idclev 463035818

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

4
หากคุณรู้ว่าคำต่อท้ายไม่ว่างเปล่า (เช่นเมื่อเป็นค่าคงที่) ดังนั้น: ส่งคืนข้อความ [: - len (คำต่อท้าย)]
MarcH

4
ขอบคุณ บรรทัดสุดท้ายอาจสั้นลง:return text[:-len(suffix)]
Jabba

3
@ Jabba: น่าเศร้าที่ไม่ได้ผลสำหรับคำต่อท้ายที่ว่างเปล่าดังที่กล่าวถึง fuenfundachtzig
yairchu

46

เนื่องจากดูเหมือนว่ายังไม่มีใครชี้เรื่องนี้ออกมา:

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

สิ่งนี้ควรมีประสิทธิภาพมากกว่าวิธีที่ใช้split()เนื่องจากไม่มีการสร้างรายการวัตถุใหม่และวิธีนี้ใช้ได้กับสตริงที่มีหลายจุด


ว้าวนั่นเป็นเคล็ดลับที่ดี ฉันไม่สามารถทำให้มันล้มเหลว แต่ฉันก็ลำบากที่จะคิดวิธีที่มันอาจล้มเหลว ฉันชอบมัน แต่มัน "วิเศษ" มากยากที่จะรู้ว่าสิ่งนี้ทำโดยเพียงแค่ดูมัน ฉันต้องประมวลผลทางใจแต่ละส่วนเพื่อ "รับ"
DevPlayer

14
สิ่งนี้จะล้มเหลวหากไม่มีการค้นหาสตริงและจะลบอักขระตัวสุดท้ายแทน
robbat2

25

ขึ้นอยู่กับสิ่งที่คุณรู้เกี่ยวกับ URL และสิ่งที่คุณต้องทำ หากคุณรู้ว่ามันจะลงท้ายด้วย '.com' (หรือ '.net' หรือ '.org') เสมอ

 url=url[:-4]

เป็นทางออกที่เร็วที่สุด หากเป็น URL ทั่วไปมากขึ้นคุณน่าจะเข้าไปดูไลบรารี่ urlparse ที่มาพร้อมกับไพ ธ อนได้ดีกว่า

หากคุณต้องการลบทุกอย่างหลังจากสุดท้าย '.' ในสตริงแล้ว

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

จะทำงาน. หรือถ้าคุณต้องการแค่ทุกอย่างจนถึงแรก '.' จากนั้นลอง

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

16

ถ้าคุณรู้ว่ามันเป็นส่วนเสริม

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

วิธีนี้ใช้ได้ดีกับabcdc.comหรือwww.abcdc.comหรือabcdc.[anything]และสามารถขยายได้มากขึ้น




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" หรืออะไรก็ได้


5

url.rsplit ('. com', 1)

ไม่ถูกต้องนัก

สิ่งที่คุณต้องเขียนก็คือ

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

และมันก็ดูค่อนข้างกระชับ IMHO

อย่างไรก็ตามการตั้งค่าส่วนตัวของฉันคือตัวเลือกนี้เพราะใช้เพียงพารามิเตอร์เดียว:

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

1
ต้องใช้พาร์ติชัน +1 เมื่อต้องการการแบ่งเพียงครั้งเดียวเนื่องจากจะส่งคืนคำตอบเสมอ IndexError จะไม่เกิดขึ้น
Gringo Suave


2

หากคุณจำเป็นต้องตัดปลายบางส่วนของสตริงถ้ามันมีอยู่อย่างอื่นทำอะไร ทางออกที่ดีที่สุดของฉัน คุณอาจต้องการใช้หนึ่งในสองการใช้งานครั้งแรก แต่ฉันได้รวม 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'

สำหรับ 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"

สำหรับคอลเลกชันของคำต่อท้ายคงที่วิธีที่เร็วที่สุด asymptotically สำหรับการโทรจำนวนมาก:

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 ตัวแปร regex น่าจะเร็วกว่านี้สำหรับแทบทุกกรณีที่ไม่เกี่ยวข้องกับพจนานุกรมขนาดใหญ่ของคำต่อท้ายที่อาจเกิดขึ้นซึ่งไม่สามารถแสดงได้อย่างง่ายดายเป็น regex อย่างน้อยใน cPython

ใน PyPy ตัวแปร regex เกือบจะช้ากว่าสำหรับการโทรจำนวนมากหรือสายยาวแม้ว่าโมดูลใหม่จะใช้เอนจิ้น regex ที่รวบรวม DFA เป็นส่วนใหญ่ของค่าใช้จ่ายส่วนใหญ่ของแลมบ์ดาจะถูกปรับให้เหมาะสมโดย JIT

ใน cPython อย่างไรก็ตามข้อเท็จจริงที่ว่าการรันโค้ด c ของคุณสำหรับ regex นั้นเทียบได้กับข้อดีของอัลกอรึทึมของรุ่นต่อท้ายในเกือบทุกกรณี


2

หากคุณต้องการดึงเฉพาะส่วนขยาย:

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

มันทำงานร่วมกับส่วนขยายใด ๆ โดยมีจุดอื่น ๆ ที่อาจมีอยู่ในชื่อไฟล์ด้วย มันแยกสตริงเป็นรายการบนจุดและรวมโดยไม่มีองค์ประกอบสุดท้าย


2
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

เมื่อใดที่ซีพียูคอขวดอยู่แล้ว ในไดรเวอร์อาจจะ

ข้อดีของการใช้นิพจน์ทั่วไปคือการใช้รหัสซ้ำ จะทำอย่างไรถ้าคุณต้องการลบ '.me' ซึ่งมีเพียงสามตัวอักษร?

รหัสเดียวกันจะทำเคล็ดลับ:

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

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

สมมติว่าคุณต้องการลบโดเมนไม่ว่าจะเป็นอะไร (.com, .net ฯลฯ ) ฉันขอแนะนำให้ค้นหา.และลบทุกอย่างออกจากจุดนั้น

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

นี่ฉันกำลังใช้rfindการแก้ปัญหาของ URL ที่ชอบที่ควรจะลดลงไปที่ชื่อabcdc.com.netabcdc.com

หากคุณเป็นกังวลเกี่ยวกับwww.s คุณควรตรวจสอบพวกเขาอย่างชัดเจน:

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

1 in replace ใช้สำหรับ edgecases แปลก ๆ เช่น www.net.www.com

หาก URL ของคุณได้รับความวุ่นวายมากขึ้นกว่าที่ดูที่คำตอบ regex ผู้คนได้ตอบสนองด้วย


1

ฉันใช้ฟังก์ชันrstripในตัวเพื่อทำตามชอบ:

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

ความคิดที่ไม่ดี ลอง"test.ccom"ดู
Shital Shah

แต่นี่ไม่ใช่ประเด็นของคำถาม มันเพิ่งถูกขอให้เอาซับสตริงที่รู้จักออกจากปลายอีกอันหนึ่ง ทำงานได้ตามที่คาดไว้
อเล็กซ์


0

นี่เป็นการใช้งานที่สมบูรณ์แบบสำหรับนิพจน์ทั่วไป:

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

5
คุณควรเพิ่ม $ เพื่อให้แน่ใจว่าคุณกำลังจับคู่ชื่อโฮสต์ที่ลงท้ายด้วย ".com"
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
คำตอบของคุณสำหรับ Python 3.9 เป็นคำตอบที่ซ้ำกันข้างต้น คำตอบของคุณสำหรับเวอร์ชันก่อนหน้านี้ยังได้รับการตอบหลายครั้งในกระทู้นี้และจะไม่ส่งคืนสิ่งใดหากสตริงไม่มีคำต่อท้าย
Xavier Guihot
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.