Como divido uma sequência de linhas múltiplas em várias linhas?

287

Eu tenho uma literal de seqüência de caracteres de várias linhas que eu quero fazer uma operação em cada linha, assim:

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

Eu quero fazer algo como o seguinte:

for line in inputString:
    doStuff()
bradtgmurray
fonte

Respostas:

437
inputString.splitlines()

Fornecerá uma lista com cada item; o splitlines()método foi projetado para dividir cada linha em um elemento da lista.

UnkwnTech
fonte
12
+1. Eu acho que isso é melhor do que a solução aceita, porque não mexe explicitamente com o separador de linhas. Tudo funciona apenas com um método API dedicado!
Lpapp 27/08/14
12
@app, eu concordo totalmente. splitlines () é semanticamente (e funcionalmente, pois usa novas linhas universais e omite uma linha vazia à direita) melhor que split ('\ n'). Naquela época (2008) eu era apenas um novato em Pythonista e grepping, embora meus scripts agora mostrem que eu também estou usando splitlines () quase exclusivamente. Portanto, estou excluindo minha resposta de 104 pontos ( * soluço ... * ) e, em vez disso, endossarei esta.
Efotinis 28/08/2014
18
Isso também faz ''.splitlines() == [], não ['']como com ''.split('\n').
rightfold 30/09/14
198

Como os outros disseram:

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

Isso é idêntico ao acima, mas as funções do módulo de string estão obsoletas e devem ser evitadas:

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

Como alternativa, se você deseja que cada linha inclua a sequência de interrupção (CR, LF, CRLF), use o splitlinesmétodo com um Trueargumento:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']
efotinis
fonte
12
Isso funcionará apenas em sistemas que usam '\ n' como terminador de linha.
Jeremy Cantrell
20
@ Jeremy: literais de string com aspas triplas sempre usam um '\ n' EOL, independentemente da plataforma. Os arquivos também são lidos no modo de texto.
Efotinis 6/10/08
16
inputString.split(os.linesep)usará o terminador de linha específico da plataforma.
James
10
É estranho que essa resposta seja tão votada. Codificação embutida '\ n' é uma péssima idéia, mas mesmo se você usar o os.linesep, terá problemas com as extremidades da linha do Windows no Linux e vice-versa, etc. Além disso, está promovendo linhas divididas com o argumento True provavelmente a forma menos comum de usá-lo ...
lpapp
4
Uma combinação de um método subótimo, um método obsoleto e uma variação redundante do método ideal.
GTC
50

Usestr.splitlines() .

splitlines()lida com as novas linhas corretamente, diferentemente split("\n").

Ele também tem a vantagem mencionada por @efotinis de incluir opcionalmente o caractere de nova linha no resultado da divisão quando chamado com um Trueargumento.


Explicação detalhada sobre por que você não deve usar split("\n"):

\n, em Python, representa uma quebra de linha do Unix (código decimal ASCII 10), independentemente da plataforma em que você a executa. No entanto, a representação de quebra de linha depende da plataforma . No Windows, \nhá dois caracteres CRe LF(códigos decimais ASCII 13 e 10, AKA \re \n), enquanto em qualquer Unix moderno (incluindo OS X), é o caractere único LF.

print, por exemplo, funciona corretamente, mesmo que você tenha uma string com terminações de linha que não correspondem à sua plataforma:

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

No entanto, a divisão explícita em "\ n" produzirá um comportamento dependente da plataforma:

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

Mesmo se você usar os.linesep, ele só será dividido de acordo com o separador de nova linha na sua plataforma e falhará se você estiver processando o texto criado em outras plataformas ou com apenas um \n:

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

splitlines resolve todos estes problemas:

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

A leitura de arquivos no modo de texto atenua parcialmente o problema de representação de nova linha, pois converte o Python \nna representação de nova linha da plataforma. No entanto, o modo de texto existe apenas no Windows. Nos sistemas Unix, todos os arquivos são abertos no modo binário; portanto, o uso split('\n')em um sistema UNIX com um arquivo do Windows levará a um comportamento indesejado. Além disso, não é incomum processar seqüências de caracteres com novas linhas potencialmente diferentes de outras fontes, como de um soquete.

goncalopp
fonte
A comparação não é justa porque você também pode usar split (os.linesep) para evitar o bit específico da plataforma.
Lpapp
6
@lpapp note que splitlinesserá dividido em qualquer final de linha. split(os.linesep)irá falhar ao ler um arquivo do Windows no UNIX, por exemplo
goncalopp
1
Outro motivo para usar linhas divididas no meu caso, obrigado. Eu dei um +1. Pessoalmente, eu incorporaria as informações nos comentários em sua resposta.
Lpapp 27/08/14
20

Pode ser um exagero nesse caso específico, mas outra opção envolve o uso StringIOpara criar um objeto parecido com um arquivo

for line in StringIO.StringIO(inputString):
    doStuff()
iruvar
fonte
Sim, esta é a abordagem mais idiomática e mais Python-ic.
O Croissant Paramagnético
4
Uma vantagem desse método, quando comparado a str.split, não é a necessidade de alocar memória (ele lê a string no local). Uma desvantagem é que é muito mais lento se você usarStringIO (cerca de 50x). Se você usar cStringIO, no entanto, é cerca de 2x mais rápido
goncalopp
2x mais rápido que o que?
Irina Rapoport
1
@IrinaRapoport, cStringIO é 2x mais rápido que o StringIO
iruvar
1

A postagem original solicitada pelo código que imprime algumas linhas (se forem verdadeiras para alguma condição) mais a seguinte linha. Minha implementação seria 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
fonte
0

Gostaria que os comentários tivessem uma formatação de texto de código adequada, porque acho que a resposta do @ 1_CR precisa de mais solavancos e gostaria de aumentar sua resposta. Enfim, ele me levou à seguinte técnica; ele usará o cStringIO, se disponível (MAS OBSERVAÇÃO: cStringIO e StringIO não são os mesmos , porque você não pode subclassificar o cStringIO ... é um built-in ... mas, para operações básicas, a sintaxe será idêntica, para que você possa fazer isso ):

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

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