¿Cómo divido una cadena de varias líneas en varias líneas?

287

Tengo un literal de cadena de varias líneas que quiero hacer una operación en cada línea, así:

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

Quiero hacer algo como lo siguiente:

for line in inputString:
    doStuff()
Bradtgmurray
fuente

Respuestas:

437
inputString.splitlines()

Le dará una lista con cada elemento, el splitlines()método está diseñado para dividir cada línea en un elemento de la lista.

UnkwnTech
fuente
12
+1. Creo que esto es mejor que la solución aceptada porque no interfiere explícitamente con el separador de línea. ¡Todo funciona con un método API dedicado!
lpapp
12
@lpapp, estoy totalmente de acuerdo. splitlines () es semánticamente (y funcionalmente, ya que usa líneas nuevas universales y omite una línea vacía final) mejor que split ('\ n'). En aquel entonces (2008) era solo un Pythonista novato y grepping aunque mis scripts ahora muestran que yo también estoy usando splitlines () casi exclusivamente. Por lo tanto, estoy borrando mi respuesta de 104 puntos ( * sob ... * ) y en su lugar voy a respaldar esta.
efotinis
18
Esto también hace ''.splitlines() == [], no ['']como con ''.split('\n').
derecha el
198

Como los otros dijeron:

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

Esto es idéntico a lo anterior, pero las funciones del módulo de cadena están en desuso y deben evitarse:

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

Alternativamente, si desea que cada línea incluya la secuencia de corte (CR, LF, CRLF), use el splitlinesmétodo con un Trueargumento:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']
efotinis
fuente
12
Esto solo funcionará en sistemas que usan '\ n' como terminador de línea.
Jeremy Cantrell
20
@Jeremy: los literales de cadena entre comillas triples siempre usan una EOL '\ n', independientemente de la plataforma. Entonces, los archivos se leen en modo texto.
efotinis
16
inputString.split(os.linesep)utilizará el terminador de línea específico de la plataforma.
James
10
Es extraño que esta respuesta sea tan votada. La codificación rígida '\ n' es una mala idea, pero incluso si usa os.linesep en lugar de eso, tendrá problemas con los extremos de línea de Windows en Linux y viceversa, etc. Además, está promoviendo líneas de división con argumento True que es probablemente la forma menos común de usarlo ...
lpapp
44
Una combinación de un método subóptimo, un método obsoleto y una variación redundante del método óptimo.
jwg
50

Usostr.splitlines() .

splitlines()maneja las nuevas líneas correctamente, a diferencia split("\n").

También tiene la ventaja mencionada por @efotinis de incluir opcionalmente el carácter de nueva línea en el resultado dividido cuando se llama con un Trueargumento.


Explicación detallada sobre por qué no debe usar split("\n"):

\n, en Python, representa un salto de línea Unix (código decimal ASCII 10), independientemente de la plataforma donde lo ejecute. Sin embargo, la representación de salto de línea depende de la plataforma . En Windows, \ntiene dos caracteres, CRy LF(códigos decimales ASCII 13 y 10, AKA \ry \n), mientras que en cualquier Unix moderno (incluido OS X), es el carácter único LF.

print, por ejemplo, funciona correctamente incluso si tiene una cadena con terminaciones de línea que no coinciden con su plataforma:

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

Sin embargo, dividirse explícitamente en "\ n", generará un comportamiento dependiente de la plataforma:

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

Incluso si lo usa os.linesep, solo se dividirá de acuerdo con el separador de nueva línea en su plataforma, y ​​fallará si está procesando texto creado en otras plataformas, o simplemente \n:

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

splitlines resuelve todos estos problemas:

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

La lectura de archivos en modo de texto mitiga parcialmente el problema de la representación de nueva línea, ya que convierte Python \nen la representación de nueva línea de la plataforma. Sin embargo, el modo de texto solo existe en Windows. En los sistemas Unix, todos los archivos se abren en modo binario, por lo que su uso split('\n')en un sistema UNIX con un archivo de Windows provocará un comportamiento no deseado. Además, no es inusual procesar cadenas con líneas nuevas potencialmente diferentes de otras fuentes, como desde un socket.

goncalopp
fuente
La comparación no es justa porque también podría usar split (os.linesep) para evitar el bit específico de la plataforma.
lpapp
66
@lpapp nota que splitlinesse dividirá en cualquier final de línea. split(os.linesep)fallará al leer un archivo de Windows en Unix, por ejemplo
goncalopp
1
Otra razón para usar splitlines en mi caso, gracias. Le di un +1. Personalmente, incluso incorporaría la información en los comentarios en su respuesta.
lpapp
20

Podría ser excesivo en este caso particular, pero otra opción implica usar StringIOpara crear un objeto similar a un archivo

for line in StringIO.StringIO(inputString):
    doStuff()
iruvar
fuente
Sí, este es el enfoque más idiomático, más Python-ic.
El cruasán paramagnético
44
Una ventaja de este método, en comparación con str.split, es que no necesita asignar memoria (lee la cadena en el lugar). Una desventaja es que es mucho más lento si lo usaStringIO (aproximadamente 50x). cStringIOSin embargo,
veces
¿2 veces más rápido que qué?
Irina Rapoport
1
@IrinaRapoport, cStringIO es 2 veces más rápido que StringIO
iruvar
1

La publicación original solicitó el código que imprime algunas filas (si son ciertas para alguna condición) más la siguiente fila. Mi implementación sería esta:

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

Deseo que los comentarios tengan el formato de texto de código adecuado, porque creo que la respuesta de @ 1_CR necesita más protuberancias, y me gustaría aumentar su respuesta. De todos modos, me llevó a la siguiente técnica; usará cStringIO si está disponible (PERO NOTA: cStringIO y StringIO no son lo mismo , porque no se puede subclasificar cStringIO ... es una función incorporada ... pero para las operaciones básicas la sintaxis será idéntica, por lo que puede hacer esto ):

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

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