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()
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:
inputString.splitlines()
Ti fornirà un elenco con ogni elemento, il splitlines()
metodo è progettato per dividere ogni riga in un elemento elenco.
''.splitlines() == []
, non ['']
come con ''.split('\n')
.
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 splitlines
metodo con un True
argomento:
inputString.splitlines(True) # --> ['Line 1\n', 'Line 2\n', 'Line 3']
inputString.split(os.linesep)
utilizzerà il terminatore di linea specifico della piattaforma.
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 True
argomento.
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, \n
sono due caratteri CR
e LF
(codici decimali ASCII 13 e 10, AKA \r
e \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 \n
nella 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.
splitlines
si dividerà su qualsiasi fine riga. split(os.linesep)
fallirà durante la lettura di un file Windows in Unix, ad esempio
Potrebbe essere eccessivo in questo caso particolare, ma un'altra opzione prevede l'utilizzo StringIO
per creare un oggetto simile a un file
for line in StringIO.StringIO(inputString):
doStuff()
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
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])
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()