Bagaimana cara membagi string multi-baris menjadi beberapa baris?

287

Saya memiliki string multi-line literal yang ingin saya lakukan operasi pada setiap baris, seperti:

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

Saya ingin melakukan sesuatu seperti berikut:

for line in inputString:
    doStuff()
bradtgmurray
sumber

Jawaban:

437
inputString.splitlines()

Akan memberi Anda daftar dengan setiap item, splitlines()metode ini dirancang untuk membagi setiap baris menjadi elemen daftar.

UnkwnTech
sumber
12
+1. Saya pikir ini lebih baik daripada solusi yang diterima karena tidak mengacaukan garis pemisah secara eksplisit. Semuanya bekerja dengan metode API khusus!
lpapp
12
@ lpapp, saya setuju sepenuhnya. splitlines () secara semantik (dan secara fungsional, karena menggunakan baris baru universal dan menghilangkan garis kosong yang tertinggal) lebih baik daripada split ('\ n'). Saat itu (2008) saya hanya seorang pemula Pythonista dan memahami meskipun skrip saya sekarang menunjukkan bahwa saya juga menggunakan splitlines () hampir secara eksklusif. Karena itu saya menghapus jawaban 104 poin saya ( * hiks ... * ) dan akan mengesahkan jawaban ini.
efotinis
18
Ini juga membuat ''.splitlines() == [], bukan ['']dengan ''.split('\n').
sayap kanan
198

Seperti yang dikatakan orang lain:

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

Ini identik dengan yang di atas, tetapi fungsi modul string sudah usang dan harus dihindari:

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

Atau, jika Anda ingin setiap baris menyertakan urutan istirahat (CR, LF, CRLF), gunakan splitlinesmetode ini dengan Trueargumen:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']
efotinis
sumber
12
Ini hanya akan bekerja pada sistem yang menggunakan '\ n' sebagai terminator garis.
Jeremy Cantrell
20
@Jeremy: Literal string yang dikutip tiga kali lipat selalu menggunakan EOL '\ n', apa pun platformnya. Begitu juga file membaca dalam mode teks.
efotinis
16
inputString.split(os.linesep)akan menggunakan terminator jalur khusus platform.
James
10
Sungguh aneh bahwa jawaban ini begitu terangkat. Pengodean keras '\ n' adalah ide yang buruk, tetapi bahkan jika Anda menggunakan os.linesep alih-alih, Anda akan memiliki masalah dengan ujung-ujung jendela di Linux dan sebaliknya, dll. Selain itu, ini mempromosikan splitlines dengan argumen True yang merupakan kemungkinan cara yang kurang umum untuk menggunakannya ...
lpapp
4
Kombinasi metode suboptimal, metode usang, dan variasi redundan dari metode optimal.
jwg
50

Menggunakan str.splitlines() .

splitlines() menangani baris baru dengan benar, tidak seperti split("\n") .

Ini juga memiliki keunggulan yang disebutkan oleh @efotinis secara opsional termasuk karakter baris baru dalam hasil split ketika dipanggil dengan Trueargumen.


Penjelasan terperinci tentang mengapa Anda tidak harus menggunakan split("\n"):

\n, dengan Python, merepresentasikan line-break Unix (kode desimal ASCII 10), terlepas dari platform tempat Anda menjalankannya. Namun, representasi linebreak bergantung pada platform . Pada Windows, \nadalah dua karakter, CRdan LF(ASCII kode desimal 13 dan 10, AKA \rdan \n), sedangkan pada setiap Unix modern (termasuk OS X), itu adalah karakter tunggal LF.

print, misalnya, berfungsi dengan benar bahkan jika Anda memiliki string dengan ujung garis yang tidak cocok dengan platform Anda:

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

Namun, pemisahan secara eksplisit pada "\ n", akan menghasilkan perilaku yang bergantung pada platform:

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

Bahkan jika Anda menggunakan os.linesep, itu hanya akan terpecah sesuai dengan pemisah baris baru pada platform Anda, dan akan gagal jika Anda sedang memproses teks yang dibuat di platform lain, atau dengan telanjang \n:

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

splitlines menyelesaikan semua masalah ini:

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

Membaca file dalam mode teks sebagian mengurangi masalah representasi baris baru, karena mengubah Python \nmenjadi representasi baris baru platform. Namun, mode teks hanya ada di Windows. Pada sistem Unix, semua file dibuka dalam mode biner, jadi menggunakan split('\n')sistem UNIX dengan file Windows akan menyebabkan perilaku yang tidak diinginkan. Selain itu, tidak biasa untuk memproses string dengan baris baru yang berpotensi berbeda dari sumber lain, seperti dari soket.

goncalopp
sumber
Perbandingannya tidak adil karena Anda juga bisa menggunakan split (os.linesep), untuk menghindari bit spesifik platform.
lpapp
6
@ lpapp note yang splitlinesakan dipisah pada akhir baris apa pun . split(os.linesep)akan gagal ketika membaca file windows di unix, misalnya
goncalopp
1
Alasan lain untuk menggunakan splitlines dalam kasus saya, terima kasih. Saya memberi +1. Saya pribadi bahkan akan memasukkan informasi dalam komentar ke dalam jawaban Anda.
lpapp
20

Mungkin berlebihan dalam kasus khusus ini tetapi opsi lain melibatkan penggunaan StringIOuntuk membuat objek seperti file

for line in StringIO.StringIO(inputString):
    doStuff()
iruvar
sumber
Ya, ini adalah pendekatan Python-ic yang paling idiomatis.
The Paramagnetic Croissant
4
Keuntungan dari metode ini, jika dibandingkan dengan str.split, tidak perlu mengalokasikan memori apa pun (membaca string di tempat). Kerugiannya adalah jauh lebih lambat jika Anda menggunakanStringIO (sekitar 50x). Namun, jika Anda menggunakannya cStringIO, ini 2x lebih cepat
goncalopp
2x lebih cepat dari apa?
Irina Rapoport
1
@IrinaRapoport, cStringIO 2x lebih cepat dari StringIO
iruvar
1

Posting asli meminta kode yang mencetak beberapa baris (jika benar untuk beberapa kondisi) ditambah baris berikut. Implementasi saya adalah ini:

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])
Finrod Felagund
sumber
0

Saya berharap komentar memiliki format teks kode yang tepat, karena saya pikir jawaban @ 1_CR perlu lebih banyak gundukan, dan saya ingin menambah jawabannya. Bagaimanapun, Dia membawa saya ke teknik berikut; ia akan menggunakan cStringIO jika tersedia (TETAPI CATATAN: cStringIO dan StringIO tidak sama , karena Anda tidak dapat mensubklasifikasikan cStringIO ... itu adalah built-in ... tetapi untuk operasi dasar sintaksinya akan sama, sehingga Anda dapat melakukan ini ):

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

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
Mike S
sumber