Come divido una stringa multilinea in più righe?


287

Ho una stringa multilinea letterale che voglio fare un'operazione su ogni riga, in questo modo:

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

Voglio fare qualcosa di simile al seguente:

for line in inputString:
    doStuff()

Risposte:


438
inputString.splitlines()

Ti fornirà un elenco con ogni elemento, il splitlines()metodo è progettato per dividere ogni riga in un elemento elenco.


12
+1. Penso che sia migliore della soluzione accettata perché non si scherza esplicitamente con il separatore di riga. Funziona solo con un metodo API dedicato!
lpapp,

12
@lpapp, sono totalmente d'accordo. splitlines () è semanticamente (e funzionalmente, poiché utilizza newline universali e omette una riga vuota finale) meglio di split ('\ n'). All'epoca (2008) ero solo un neofita di Pythonista e facevo il grepping anche se i miei script ora mostrano che anch'io sto usando splitline () quasi esclusivamente. Pertanto sto eliminando la mia risposta da 104 punti ( * sob ... * ) e approverò invece questa.
efotinis,

18
Questo rende anche ''.splitlines() == [], non ['']come con ''.split('\n').
bendaggio

198

Come hanno detto gli altri:

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

Questo è identico a quanto sopra, ma le funzioni del modulo stringa sono obsolete e dovrebbero essere evitate:

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

In alternativa, se si desidera che ciascuna riga includa la sequenza di interruzioni (CR, LF, CRLF), utilizzare il splitlinesmetodo con un Trueargomento:

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

12
Funzionerà solo su sistemi che usano '\ n' come terminatore di linea.
Jeremy Cantrell,

20
@Jeremy: i letterali di stringhe a tre virgolette usano sempre un EOL '\ n', indipendentemente dalla piattaforma. Quindi i file vengono letti in modalità testo.
efotinis,

16
inputString.split(os.linesep)utilizzerà il terminatore di linea specifico della piattaforma.
James,

10
È strano che questa risposta sia così votata. La codifica hardware '\ n' è una cattiva idea, ma anche se usi os.linesep invece, avrai problemi con le estremità delle linee di Windows su Linux e viceversa, ecc. Inoltre, promuove le splitline con l'argomento True che è probabilmente il modo meno comune di usarlo ...
lpapp

4
Una combinazione di un metodo non ottimale, un metodo deprecato e una variazione ridondante del metodo ottimale.
jwg

50

Uso str.splitlines() .

splitlines()gestisce le nuove righe correttamente, a differenza split("\n").

Ha anche il vantaggio menzionato da @efotin di includere facoltativamente il carattere di nuova riga nel risultato diviso quando viene chiamato con un Trueargomento.


Spiegazione dettagliata sul perché non dovresti usare split("\n"):

\n, in Python, rappresenta un'interruzione di riga Unix (codice decimale ASCII 10), indipendentemente dalla piattaforma in cui viene eseguita. Tuttavia, la rappresentazione dell'interruzione di linea dipende dalla piattaforma . Su Windows, \nsono due caratteri CRe LF(codici decimali ASCII 13 e 10, AKA \re \n), mentre su qualsiasi Unix moderno (incluso OS X), è il singolo carattere LF.

print, ad esempio, funziona correttamente anche se hai una stringa con terminazioni di riga che non corrispondono alla tua piattaforma:

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

Tuttavia, la divisione esplicita su "\ n" produrrà un comportamento dipendente dalla piattaforma:

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

Anche se lo usi os.linesep, si dividerà solo in base al separatore di nuova riga sulla tua piattaforma e fallirà se stai elaborando del testo creato in altre piattaforme o con un nudo \n:

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

splitlines risolve tutti questi problemi:

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

La lettura dei file in modalità testo attenua parzialmente il problema della rappresentazione della nuova riga, in quanto converte Python \nnella rappresentazione della nuova riga della piattaforma. Tuttavia, la modalità testo esiste solo su Windows. Sui sistemi Unix, tutti i file vengono aperti in modalità binaria, quindi l'utilizzo split('\n')in un sistema UNIX con un file Windows comporterà comportamenti indesiderati. Inoltre, non è insolito elaborare stringhe con newline potenzialmente diverse da altre fonti, ad esempio da un socket.


Il confronto non è corretto perché è possibile utilizzare anche split (os.linesep) per evitare il bit specifico della piattaforma.
lpapp,

6
Nota @lpapp che splitlinessi dividerà su qualsiasi fine riga. split(os.linesep)fallirà durante la lettura di un file Windows in Unix, ad esempio
goncalopp

1
Un altro motivo per usare le splitline nel mio caso, grazie. Ho dato un +1. Personalmente vorrei anche incorporare le informazioni nei commenti nella tua risposta.
lpapp,

20

Potrebbe essere eccessivo in questo caso particolare, ma un'altra opzione prevede l'utilizzo StringIOper creare un oggetto simile a un file

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

Sì, questo è l'approccio più idiomatico, più Python-ic.
The Paramagnetic Croissant,

4
Un vantaggio di questo metodo, se confrontato con str.split, non è necessario allocare memoria (legge la stringa sul posto). Uno svantaggio è che è molto più lento se si utilizzaStringIO (circa 50x). Se usi cStringIO, tuttavia, è circa 2 volte più veloce
goncalopp,

2 volte più veloce di cosa?
Irina Rapoport,

1
@IrinaRapoport, cStringIO è 2x più veloce di StringIO
iruvar

1

Il post originale ha richiesto il codice che stampa alcune righe (se sono vere per alcune condizioni) più la riga seguente. La mia implementazione sarebbe questa:

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

Vorrei che i commenti avessero una corretta formattazione del testo in codice, perché penso che la risposta di @ 1_CR abbia bisogno di più rilievi e vorrei aumentare la sua risposta. Comunque, mi ha portato alla seguente tecnica; utilizzerà cStringIO se disponibile (MA NOTA: cStringIO e StringIO non sono gli stessi , perché non è possibile sottoclassare cStringIO ... è un built-in ... ma per le operazioni di base la sintassi sarà identica, quindi puoi farlo ):

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

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.