Bir dizenin sol kısmı nasıl kaldırılır?


144

Ben bir dize örneğin arar dosyaları bazı basit piton kodu var path=c:\path, c:\pathbölüm değişebilir. Mevcut kod:

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=" ?

Metni sonra almanın basit bir yolu nedir Path=?


"Path =" ile başlayan dosyadaki ilk satır oluşumunu döndürdüğünüzü unutmayın. Bu yazının diğer cevapları da var. Ancak dosya bir DOS toplu iş dosyası gibi bir şeyse, "toplu iş" veya komut dosyası koşullarla dolu değilse bağlı olarak böyle bir dosyadan son satırın ortaya çıkmasını isteyebilirsiniz.
DevPlayer

Yanıtlar:



196

Dize sabitse şunları kullanabilirsiniz:

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

size dize içindeki konum 5'ten itibaren her şeyi verir (bir dize de bir dizidir, böylece bu dizi işleçleri de burada çalışır).

Veya ilk başta çizgiyi bölebilirsiniz =:

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

O zaman param "Path" ve değer, first = öğesinden sonra kalan değerdir.


3
Bölme yöntemi için +1, len (önek) üzerinde manuel dilimlemenin hafif çirkinliğini önler.
bobince

1
Ancak girdileriniz "bir şey = bir şey" biçiminde değilse de atar.
Dan Olson

1
Bu yüzden koşulu öne koydum, bu yüzden sadece dizede bir "=" varsa kullanılır. Aksi takdirde, split () sonucunun uzunluğunu ve == 2 olup olmadığını da test edebilirsiniz.
MrTopf

7
Dan Olson'ın dediği gibi split, sınırlayıcı yoksa bir istisna atar. partitiondaha kararlı, aynı zamanda bir dize böler ve her zaman ön, sınırlayıcı ve içerik sonrası (bazıları ''sınırlayıcı yoksa olabilir) üç elemanlı bir demet döndürür . Ör value = line.partition('=').
Anders Johansson

1
Ayrılmış sınırlanmış yoksa Split bir istisna atmaz, dizenin tamamını içeren bir liste döndürür. En azından python 2.7 altında
Maxim

122

Bir dizeden öneki kaldır

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

Ayırıcının ilk ortaya çıkışında 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

INI benzeri dosyayı ConfigParser ile ayrıştırma

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

Diğer seçenekler


1
Dört yerine üç boşluk girintisinin nadir bir nedeni.
Bob Stein

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

1
Ben bunu "else metin" yerine "else False" veya "else None" ya da ne olursa olsun -type- dosyadaki satır "Path =" ile başlamadığını belirtmek için dönmek istediğiniz için değiştirebilirsiniz. Kişisel olarak üçlü operatörlerimi görsel olarak öne çıkmak için parantez içine almayı seviyorum.
DevPlayer

19

Genel olarak dilimleme (koşullu veya koşulsuz) için bir meslektaşımın son zamanlarda önerilerini tercih ederim; Boş bir dize ile değiştirme kullanın. Kodu okumak daha kolay, daha az kod (bazen) ve yanlış sayıda karakter belirtme riski daha az. Tamam; Python kullanmıyorum, ancak diğer dillerde bu yaklaşımı tercih ediyorum:

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

ya da - bu gönderinin ilk yorumunu takip etmek için - eğer bu sadece satırın başlaması ile yapılacaksa Path:

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

Yukarıda önerilenlerden bazılarının ana farkı, hiçbir "sihirli sayı" (5) olmaması ya da hem ' 5' hem de dize ' Path=' belirtilmesi gerekmemesi , Diğer bir deyişle, bu yaklaşımı bir kod bakımından tercih ediyorum bakış açısı.


Çalışmıyor: 'c = Path = a'.replace ("Path =", "", 1) ->' c = a '.
jfs

3
Bu, "Path =" ile başlayan dizenin özgün gereksinimlerini karşılamıyor.
Köpek yavrusu

1
Normal ifade kodunu sadece ile değiştirebilirsiniz rightmost = re.sub('^Path=', '', fullPath). compile()Yöntemin amacı , derlenen nesneyi yeniden kullanırsanız işleri daha hızlı hale getirmektir, ancak onu kullandıktan sonra attığınızdan, burada yine de bir etkisi yoktur. Zaten bu optimizasyon konusunda endişelenmeye değmez.
Jim Oldfield

13

popDizinlemeyi tercih ederim [-1]:

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

için

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

2
"Sihirli sayılar" olmadan güzel bir alternatif. Bunun işe yaradığından startswith, daha önce test edilmiş olduğundan , daha önce split"hiçbir şeyi" ve daha sonra her şeyi bölecağını belirtmek gerekir . split("Path=", 1)daha hassastır (ön ekin daha sonra dizede görünmesi durumunda), ancak sihirli bir sayı verir.
quornian

1
(Çok önemli) önceki yorumun daha kısa versiyonu: bu SADECE önce startswith () ile test ederseniz çalışır.
MarcH

12

Ya da neden olmasın

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


5

Düşünebildiğim en basit yol dilimleme ile:

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

Dilim gösterimi hakkında hızlı bir not, her zamanki yerine iki endeks kullanır. İlk dizin, diziye dahil etmek istediğiniz dizinin ilk öğesini belirtir ve son dizin, dilime dahil etmek istediğiniz son öğenin hemen sonundaki dizindir.
Örneğin:

sequence_obj[first_index:last_index]

Dilim first_indexve arasındaki tüm öğelerden oluşurlast_index de dahil olmak üzere first_indexolup last_index. İlk dizin atlanırsa, varsayılan olarak dizinin başlangıcıdır. Son dizin atlanırsa, dizideki son öğeye kadar olan tüm öğeleri içerir. Olumsuz endekslere de izin verilir. Konu hakkında daha fazla bilgi edinmek için Google'ı kullanın.


4
>>> import re

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

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

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

1. r''Windows yolları için dizeleri kullanın . 2. re.match()Hiçbiri geri dönebilir
jfs

3

Burada bahsedilmeyen bir başka basit tek astar:

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

Bu, çeşitli kenar durumlarda da düzgün çalışır:

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

line[5:]istediğiniz alt dizeyi verecektir. Giriş bölümünde arama yapın ve 'dilim gösterimi'ni arayın


1

Liste kavrayışlarını biliyorsanız:

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

line.startswith(...)10 kat daha hızlı olduğunu belirten bir düzenleme yapıldı . Testlerim bunu doğrulamadı. Bu iddiayı destekleyen kanıtlar sağlanmışsa değiştirmekten mutluluk duyarız.
Matthew Schinckel

0

Pop sürümü tam olarak doğru değildi. Bence sen istiyorsun:

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

0

Neden regex'i kaçış ile kullanmıyorsunuz? ^satırın ilk kısmıyla ve re.MULTILINEher satırla eşleşir. re.escapeeşleşmenin tam olmasını sağlar.

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

0

Aşağıdaki kodu deneyin

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

1
Cevabınız ile kabul edilen cevap arasındaki fark nedir? Diğer cevabın ilk bölümünde olduğunu görüyorum.
eyllanesc

-1

Tam olarak aradığın şey sanırım

    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

bir işlev yazmak zorunda kalmadan, bu, listeye göre bölünecektir, bu durumda 'Bay | Dr. | Mrs.', [1] ile bölüntükten sonra her şeyi seçip tekrar bölün ve hangi öğeyi yakalarsınız. Aşağıdaki durumda, 'Morris' iade edilir.

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

-1

Bu teknikte diğer cevaplara çok benzer, ancak tekrarlanan dize işlemleri olmadan, ön ekin orada olup olmadığını söyleme yeteneği ve hala oldukça okunabilir:

parts = the_string.split(prefix_to_remove, 1):
    if len(parts) == 2:
        #  do things with parts[1]
        pass
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.