Çok satırlı bir dizeyi birden çok satıra nasıl bölerim?


287

Her satırda bir işlem yapmak istediğiniz gibi çok satırlı dize değişmez var, bu yüzden:

inputString = """Line 1
Line 2
Line 3"""

Aşağıdaki gibi bir şey yapmak istiyorum:

for line in inputString:
    doStuff()

Yanıtlar:


438
inputString.splitlines()

Her öğeyle birlikte bir liste verecek, splitlines()yöntem her satırı bir liste öğesine bölmek için tasarlanmıştır.


12
+1. Bu, kabul edilen çözümden daha güzel olduğunu düşünüyorum, çünkü çizgi ayırıcıyla açıkça karışmıyor. Her şey sadece özel bir API yöntemiyle çalışır!
lpapp

12
@lpapp, tamamen katılıyorum. splitlines () anlamsaldır (ve işlevsel olarak, çünkü evrensel yeni satırlar kullanır ve boş satırdan çıkar) bölünmeden ('\ n') daha iyidir. O zamanlar (2008) Ben sadece bir acemi Pythonista ve selamlama rağmen benim komut dosyaları şimdi ben de sadece splitlines () kullandığımı gösteriyor. Bu nedenle 104 puanlık cevabımı siliyorum ( * sob ... * ) ve bunun yerine bunu onaylayacağım.
efotinis

18
Bu da olduğu gibi ''.splitlines() == []değil . ['']''.split('\n')
sağ kanat

198

Diğerlerinin söylediği gibi:

inputString.split('\n')  # --> ['Line 1', 'Line 2', 'Line 3']

Bu yukarıdakilerle aynıdır, ancak dize modülünün işlevleri kullanımdan kaldırılmıştır ve bundan kaçınılmalıdır:

import string
string.split(inputString, '\n')  # --> ['Line 1', 'Line 2', 'Line 3']

Alternatif olarak, her satırın kesme sırasını (CR, LF, CRLF) içermesini istiyorsanız, splitlinesyöntemi Truebağımsız değişkenle kullanın:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']

12
Bu yalnızca '\ n' satır sonlandırıcı olarak kullanılan sistemlerde çalışır.
Jeremy Cantrell

20
@Jeremy: Üç tırnaklı dize değişmezleri, platformdan bağımsız olarak her zaman '\ n' EOL kullanır. Dosyalar metin modunda da okunuyor.
efotinis

16
inputString.split(os.linesep)platforma özel hat sonlandırıcısını kullanacaktır.
James

10
Bu cevabın bu kadar yükseltilmesi garip. Sabit kodlama '\ n' kötü bir fikirdir, ancak bunun yerine os.linesep'i kullansanız bile, Linux'ta windows satır uçlarıyla ilgili sorunlar yaşayacaksınız ve bunun tersi, vb. Ayrıca, True argümanı ile splitlines teşvik ediyor muhtemelen kullanmanın daha az yaygın yolu ...
lpapp

4
Optimal bir yöntemin, kullanımdan kaldırılmış bir yöntemin ve optimum yöntemin gereksiz bir varyasyonunun bir kombinasyonu.
jwg

50

Kullanınstr.splitlines() .

splitlines()aksine yeni satırları düzgün işler split("\n").

Ayrıca, @efotinis tarafından, isteğe bağlı olarak, Truebağımsız değişken çağrıldığında yeni satır karakterini bölünmüş sonuca dahil etme avantajı vardır .


Neden kullanmamanız gerektiğine dair ayrıntılı açıklama split("\n"):

\n, Python'da, çalıştırdığınız platformdan bağımsız olarak bir Unix satır sonunu (ASCII ondalık kodu 10) temsil eder. Ancak, linebreak temsili platforma bağlıdır . Windows'da \niki karakter CRve LF(ASCII ondalık kodları 13 ve 10, AKA \rve \n), herhangi bir modern Unix'te (OS X dahil), tek karakterdir LF.

printörneğin, platformunuzla eşleşmeyen satır sonlarına sahip bir dizeniz olsa bile doğru şekilde çalışır:

>>> print " a \n b \r\n c "
 a 
 b 
 c

Ancak, açıkça "\ n" üzerine bölmek, platforma bağlı davranış sağlar:

>>> " a \n b \r\n c ".split("\n")
[' a ', ' b \r', ' c ']

Kullansanız bile os.linesep, yalnızca platformunuzdaki yeni satır ayırıcısına göre bölünür ve diğer platformlarda veya çıplak bir şekilde oluşturulmuş metni işlerseniz başarısız olur \n:

>>> " a \n b \r\n c ".split(os.linesep)
[' a \n b ', ' c ']

splitlines tüm bu sorunları çözer:

>>> " a \n b \r\n c ".splitlines()
[' a ', ' b ', ' c ']

Metin modunda dosyaları okumak , Python'ları \nplatformun yeni satır temsiline dönüştürdüğü için yeni satır temsil sorununu kısmen azaltır . Ancak, metin modu yalnızca Windows'ta bulunur. Unix sistemlerde, tüm dosyalar ikili modda açılır, bu nedenle split('\n')Windows dosyası olan bir UNIX sisteminde kullanılması istenmeyen davranışlara neden olur. Ayrıca, bir soket gibi diğer kaynaklardan potansiyel olarak farklı yeni satırlara sahip dizeleri işlemek olağandışı değildir.


Platforma özgü bitlerden kaçınmak için split (os.linesep) de kullanabileceğiniz için karşılaştırma adil değildir.
lpapp

6
@lpapp herhangi bir satır sonu splitlinesbölünecek not . Örneğin, split(os.linesep)
unix'te

1
Benim durumumda splitlines kullanmanın başka bir nedeni, teşekkürler. +1 verdim. Kişisel olarak yorumlardaki bilgileri cevabınıza dahil edebilirim.
lpapp

20

Bu özel durumda aşırıya kaçabilir, ancak başka bir seçenek StringIOdosya benzeri bir nesne oluşturmak için kullanmayı içerir

for line in StringIO.StringIO(inputString):
    doStuff()

Evet, bu en deyimsel, en Python-ic yaklaşımıdır.
Paramanyetik Kruvasan

4
Karşılaştırıldığında bu yönteme bir avantajı, str.split, olan herhangi bir bellek ayrılamadı gerek yok (o dize yerinde okur). Bir dezavantaj, kullanmanızın daha yavaş olmasıdırStringIO (yaklaşık 50x). cStringIOBununla birlikte,
goncalopp

2 kat daha hızlı?
Irina Rapoport

1
@IrinaRapoport, cStringIO, StringIO'dan 2 kat daha hızlı
iruvar

1

Bazı satırları (bazı koşullar için doğruysa) ve sonraki satırı yazdıran kod için istenen orijinal gönderi. Benim uygulama bu olurdu:

text = """1 sfasdf
asdfasdf
2 sfasdf
asdfgadfg
1 asfasdf
sdfasdgf
"""

text = text.splitlines()
rows_to_print = {}

for line in range(len(text)):
    if text[line][0] == '1':
        rows_to_print = rows_to_print | {line, line + 1}

rows_to_print = sorted(list(rows_to_print))

for i in rows_to_print:
    print(text[i])

0

@ 1_CR 'ın cevabının daha fazla yumruya ihtiyacı olduğunu düşündüğüm için yorumların uygun kod metni biçimlendirmesini diliyorum ve cevabını arttırmak istiyorum. Her neyse, beni şu tekniğe götürdü; varsa cStringIO'yu kullanır (AMA NOT: cStringIO ve StringIO aynı değildir , çünkü cStringIO'yu alt sınıflandıramazsınız ... bu yerleşiktir ... ancak temel işlemler için sözdizimi aynı olacaktır, böylece bunu yapabilirsiniz ):

try:
    import cStringIO
    StringIO = cStringIO
except ImportError:
    import StringIO

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
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.