Bagaimana cara menghapus bagian kiri dari sebuah string?


144

Saya memiliki beberapa kode python sederhana yang mencari file untuk string misalnya path=c:\path, di mana c:\pathbagian tersebut dapat bervariasi. Kode saat ini adalah:

def find_path(i_file):
    lines = open(i_file).readlines()
    for line in lines:
        if line.startswith("Path="):
            return # what to do here in order to get line content after "Path=" ?

Apa cara sederhana untuk mendapatkan teks setelahnya Path=?


Perlu diketahui bahwa Anda kembali pada kemunculan baris pertama dalam file yang dimulai dengan "Path =". Jawaban lain untuk posting ini juga dilakukan. Tetapi jika file tersebut seperti file batch DOS Anda mungkin benar-benar ingin terjadinya baris terakhir dari file seperti itu tergantung jika file "batch" atau file perintah tidak diisi dengan persyaratan.
DevPlayer

Jawaban:



196

Jika string sudah diperbaiki, Anda cukup menggunakan:

if line.startswith("Path="):
    return line[5:]

yang memberi Anda segalanya dari posisi 5 di dalam string (string juga merupakan urutan sehingga operator urutan ini juga bekerja di sini).

Atau Anda dapat membagi garis pada awalnya =:

if "=" in line:
    param, value = line.split("=",1)

Maka param adalah "Path" dan nilai adalah sisanya setelah = pertama.


3
+1 untuk metode split, menghindari sedikit kejelekan dari pengiris manual pada len (awalan).
bobince

1
Tetapi juga melempar jika input Anda tidak semuanya dalam bentuk "something = somethingelse".
Dan Olson

1
Itu sebabnya saya menempatkan kondisi di depan sehingga hanya digunakan jika "=" ada di string. Kalau tidak, Anda juga dapat menguji panjang hasil split () dan jika itu == 2.
MrTopf

7
Seperti Dan Olson mengatakan splitmelemparkan pengecualian jika pembatas tidak ada. partitionlebih stabil, ia juga membagi string dan selalu mengembalikan tuple tiga elemen dengan pre-, delimiter, dan post-content (beberapa di antaranya mungkin ''jika pembatas tidak ada). Misalnya value = line.partition('='),.
Anders Johansson

1
Split tidak melempar pengecualian jika pembatas tidak ada, ia mengembalikan daftar dengan seluruh string. Setidaknya dengan python 2.7
Maxim

122

Hapus awalan dari string

# ...
if line.startswith(prefix):
   return line[len(prefix):]

Berpisah pada kemunculan pertama pemisah via str.partition()

def findvar(filename, varname="Path", sep="=") :
    for line in open(filename):
        if line.startswith(varname + sep):
           head, sep_, tail = line.partition(sep) # instead of `str.split()`
           assert head == varname
           assert sep_ == sep
           return tail

Parse file seperti ini dengan ConfigParser

from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.read(filename) # requires section headers to be present

path = config.get(section, 'path', raw=1) # case-insensitive, no interpolation

Pilihan lain


1
Satu alasan langka untuk membuat indentasi tiga spasi, bukan empat
Bob Stein

25
def remove_prefix(text, prefix):
    return text[len(prefix):] if text.startswith(prefix) else text

1
Saya suka yang ini karena Anda dapat mengganti "else text" dengan "else False" atau "else None" atau apa pun -type- Anda ingin kembali untuk menunjukkan bahwa baris dalam file tidak dimulai dengan "Path =". Secara pribadi saya suka mengelilingi operator ternary saya dengan tanda kurung agar menonjol secara visual.
DevPlayer

19

Untuk memotong (kondisional atau non-kondisional) secara umum saya lebih suka apa yang disarankan rekan kerja baru-baru ini; Gunakan pengganti dengan string kosong. Lebih mudah membaca kode, lebih sedikit kode (kadang-kadang) dan lebih sedikit risiko menentukan jumlah karakter yang salah. Baik; Saya tidak menggunakan Python, tetapi dalam bahasa lain saya lebih suka pendekatan ini:

rightmost = full_path.replace('Path=', '', 1)

atau - untuk menindaklanjuti komentar pertama untuk posting ini - jika ini hanya boleh dilakukan jika baris dimulai dengan Path:

rightmost = re.compile('^Path=').sub('', full_path)

Perbedaan utama dengan beberapa yang telah disarankan di atas adalah bahwa tidak ada "angka ajaib" (5) yang terlibat, atau kebutuhan untuk menentukan ' 5' dan string ' Path=', Dengan kata lain saya lebih suka pendekatan ini dari pemeliharaan kode sudut pandang.


Tidak berfungsi: 'c = Path = a'.replace ("Path =", "", 1) ->' c = a '.
jfs

3
Itu tidak memenuhi persyaratan asli dari string yang dimulai dengan "Path =".
Puppy

1
Anda dapat mengganti kode regex dengan adil rightmost = re.sub('^Path=', '', fullPath). Tujuan dari compile()metode ini adalah untuk membuat segalanya lebih cepat jika Anda menggunakan kembali objek yang dikompilasi, tetapi karena Anda membuangnya setelah Anda menggunakannya, toh hal itu tidak berpengaruh di sini. Biasanya tidak perlu khawatir tentang pengoptimalan ini.
Jim Oldfield

13

Saya lebih suka poppengindeksan[-1] :

value = line.split("Path=", 1).pop()

untuk

value = line.split("Path=", 1)[1]
param, value = line.split("Path=", 1)

2
Alternatif yang bagus tanpa "angka ajaib". Perlu dicatat bahwa ini berfungsi karena startswithtelah diuji sehingga splitakan membagi "tidak ada" sebelumnya dan yang lainnya setelahnya. split("Path=", 1)lebih tepat (dalam kasus awalan muncul kembali kemudian dalam string) tetapi memperkenalkan kembali angka ajaib.
quornian

1
Versi lebih pendek dari komentar sebelumnya (sangat penting): ini HANYA berfungsi jika Anda menguji dengan startswith () terlebih dahulu.
MarcH

12

Atau mengapa tidak

if line.startswith(prefix):
    return line.replace(prefix, '', 1)

5

Bagaimana tentang..

>>> line = r'path=c:\path'
>>> line.partition('path=')
('', 'path=', 'c:\\path')

Triplet ini adalah kepala, pemisah, dan ekor .


Ini tidak bekerja dalam semua kasus dengan cara yang sama. Jika separator ada, maka hasilnya adalah item ketiga. Kalau tidak, hasilnya adalah item pertama.
Ioannis Filippidis

5

Cara paling sederhana yang bisa saya pikirkan adalah dengan mengiris:

def find_path(i_file): 
    lines = open(i_file).readlines() 
    for line in lines: 
        if line.startswith("Path=") : 
            return line[5:]

Catatan singkat tentang notasi slice, ini menggunakan dua indeks, bukan yang biasa. Indeks pertama menunjukkan elemen pertama dari urutan yang ingin Anda sertakan dalam slice dan indeks terakhir adalah indeks segera setelah elemen terakhir yang ingin Anda sertakan dalam slice.
Misalnya:

sequence_obj[first_index:last_index]

Irisan terdiri dari semua elemen antara first_indexdan last_index, termasuk first_indexdan tidak last_index. Jika indeks pertama dihilangkan, maka akan default ke awal urutan. Jika indeks terakhir dihilangkan, itu mencakup semua elemen hingga elemen terakhir dalam urutan. Indeks negatif juga diperbolehkan. Gunakan Google untuk mempelajari lebih lanjut tentang topik tersebut.


4
>>> import re

>>> p = re.compile(r'path=(.*)', re.IGNORECASE)

>>> path = "path=c:\path"

>>> re.match(p, path).group(1)
'c:\\path'

1. Gunakan r''string untuk jalur Windows. 2. re.match()dapat mengembalikan Tidak Ada
jfs

3

Satu kalimat sederhana yang belum disebutkan di sini:

value = line.split("Path=", 1)[-1]

Ini juga akan berfungsi dengan baik untuk berbagai kasus tepi:

>>> print("prefixfoobar".split("foo", 1)[-1])
"bar"

>>> print("foofoobar".split("foo", 1)[-1])
"foobar"

>>> print("foobar".split("foo", 1)[-1])
"bar"

>>> print("bar".split("foo", 1)[-1])
"bar"

>>> print("".split("foo", 1)[-1])
""



1

Jika Anda tahu daftar pemahaman:

lines = [line[5:] for line in file.readlines() if line[:5] == "Path="]

Ada pengeditan yang menyarankan line.startswith(...)10X lebih cepat. Pengujian saya tidak mengonfirmasi hal ini. Senang mengubahnya jika bukti yang mendukung pernyataan itu diberikan.
Matthew Schinckel

0

Versi popnya kurang tepat. Saya pikir Anda ingin:

>>> print('foofoobar'.split('foo', 1).pop())
foobar

0

Mengapa tidak menggunakan regex dengan melarikan diri? ^cocok dengan bagian awal dari suatu baris dan re.MULTILINEcocok pada setiap baris. re.escapememastikan bahwa pencocokan tepat.

>>> print(re.sub('^' + re.escape('path='), repl='', string='path=c:\path\nd:\path2', flags=re.MULTILINE))
c:\path
d:\path2

0

Coba ikuti kode

if line.startswith("Path="): return line[5:]

1
Apa perbedaan antara jawaban Anda dan jawaban yang diterima? Saya melihat bahwa itu ada di bagian pertama dari jawaban yang lain.
eyllanesc

-1

Saya kira inilah yang sebenarnya Anda cari

    def findPath(i_file) :
        lines = open( i_file ).readlines()
        for line in lines :
            if line.startswith( "Path=" ):
                output_line=line[(line.find("Path=")+len("Path=")):]
                return output_line

-1

tanpa harus menulis fungsi, ini akan terpecah sesuai daftar, dalam hal ini 'Tuan | Dr. | Ny.', pilih semuanya setelah dipisah dengan [1], lalu belah lagi dan ambil elemen apa pun. Dalam kasus di bawah ini, 'Morris' dikembalikan.

re.split('Mr.|Dr.|Mrs.', 'Mr. Morgan Morris')[1].split()[1]

-1

Ini sangat mirip dalam teknik dengan jawaban lain, tetapi tanpa operasi string berulang, kemampuan untuk mengetahui apakah awalan ada di sana atau tidak, dan masih cukup mudah dibaca:

parts = the_string.split(prefix_to_remove, 1):
    if len(parts) == 2:
        #  do things with parts[1]
        pass
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.