如何将多行字符串拆分成多个单独的行?

352

我有一个多行字符串,我想对每一行执行操作,像这样:

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

我想要对每一行进行迭代:

for line in inputString:
    doStuff()
7个回答

535
inputString.splitlines()

使用splitlines()方法,可以将每一行分割成列表中的一个元素。


13
我认为这个解决方案比被接受的解决方案更好,因为它不会明确地干扰行分隔符。所有的东西都可以通过一个专门的API方法来实现! - László Papp
15
@lpapp,我完全同意。 splitlines()在语义上(以及功能上,因为它使用通用换行符并省略结尾的空行)比split('\n')更好。那时(2008年),我只是一个新手Pythonista,现在搜索我的脚本显示,我几乎完全使用splitlines()。因此,我将删除我的104分答案(_悲伤..._),并支持这个答案。 - efotinis
19
这也使得''.splitlines() == [],而不是像''.split('\n')一样为[''] - user1804599

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

这与上述内容相同,但字符串模块的函数已被弃用,因此应避免使用:

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

如果您希望每行都包含换行序列(CR、LF、CRLF),可以使用 splitlines 方法,并加上 True 参数:

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

12
这只适用于使用“\n”作为行终止符的系统。 - Jeremy Cantrell
20
无论是哪个平台,三重引号的字符串字面值始终使用 '\n' 作为行尾符。在文本模式下读取文件也一样。 - efotinis
16
inputString.split(os.linesep) 会使用特定于平台的换行符来分割字符串。 - James
12
这个答案被点赞得如此之多很奇怪。硬编码 “\n” 不是一个好主意,即使你使用 os.linesep 代替它,在 Linux 上会遇到与 Windows 行结尾的问题,反之亦然,等等。此外,它在推广带有 True 参数的 splitlines,这可能不是常用的使用方式…… - László Papp
6
这是一个次优方法、一个已弃用的方法和一个冗余但不太好的最佳方法的组合。 - jwg
显示剩余2条评论

61

请使用inputString.splitlines()


为什么要使用splitlines

splitlines可以正确处理换行符,而split则不然。

当传入True参数时,splitlines可选择将分割结果中的换行符包含在内,这在某些特定场景下非常有用。


为什么不能使用split("\n")

使用split会在跨操作系统共享文件时产生非常混乱的bug。

在Python中,\n表示Unix换行符(ASCII十进制码10),与您运行它的操作系统无关。然而,ASCII换行符的表示方式是依赖于操作系统的

在Windows上,\n代表两个字符,即回车符CR和换行符LF(ASCII十进制码13和10,即\r\n),而在现代Unix系统(Mac OS X、Linux、Android)上,则是单个字符LF

print可以正确输出带有与您平台不匹配的行结尾的字符串:

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

然而,明确地在 "\n" 上分割具有依赖于操作系统的行为:

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

即使您使用 os.linesep,它也只会根据您所在平台的换行符进行分割,如果处理其他平台创建的文本或裸的 \n,则会失败:

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

splitlines 解决了所有这些问题:

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

以文本模式读取文件可以部分缓解换行符表示问题,因为它将 Python 的 \n 转换为平台的换行符表示。

然而,在 Unix 系统上,只有二进制模式。在 UNIX 系统中使用 split('\n') 与 Windows 文件会导致意外行为。这也可能发生在网络传输文件时。


比较不公平,因为你也可以使用split(os.linesep)来避免特定于平台的部分。 - László Papp
6
注意,splitlines方法会在任何换行符处分割字符串。例如,在Unix系统中读取Windows文件时,使用split(os.linesep)会导致错误。 - loopbackbee
1
在我的情况下,使用splitlines的另一个原因,谢谢。我给了一个+1。我个人甚至会将评论中的信息合并到您的答案中。 - László Papp

21

在这种情况下可能有些过度,但另一种选择是使用StringIO来创建一个类似文件的对象。

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

是的,这是最符合惯用法、最Python风格的方法。 - The Paramagnetic Croissant
5
str.split相比,这种方法的优点是不需要分配任何内存(它原地读取字符串)。缺点是如果使用StringIO,速度会慢得多(约为50倍)。然而,如果使用**cStringIO**,速度会快约2倍。 - loopbackbee
比什么快2倍? - Irina Rapoport
1
@IrinaRapoport,cStringIO比StringIO快2倍。 - iruvar

0
我想补充 @1_CR 的回答:他引导我使用以下技术;如果可用,它将使用 cStringIO (但请注意:cStringIO 和 StringIO 不同,因为您无法子类化cStringIO... 它是内置的... 但对于基本操作,语法将是相同的,所以您可以这样做):
try:
    import cStringIO
    StringIO = cStringIO
except ImportError:
    import StringIO

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

0
原帖要求编写代码,如果符合某些条件,则打印某些行以及其后面的一行。 我的实现如下:
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
在Python3中使用以下代码
from io import StringIO
for sline in sio.readlines():
        print(sline)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接