349

I have a multi-line string that I want to do an operation on each line, like so:

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

I want to iterate on each line:

for line in inputString:
    doStuff()
loopbackbee
  • 21,962
  • 10
  • 62
  • 97
bradtgmurray
  • 13,683
  • 10
  • 38
  • 36

7 Answers7

532
inputString.splitlines()

Will give you a list with each item, the splitlines() method is designed to split each line into a list element.

Aryan Beezadhur
  • 4,503
  • 4
  • 21
  • 42
UnkwnTech
  • 88,102
  • 65
  • 184
  • 229
  • 13
    +1. I think this is nicer than the accepted solution because it does not mess with the line separator explicitly. It all just works with a dedicated API method! – László Papp Aug 27 '14 at 15:23
  • 15
    @lpapp, I totally agree. splitlines() is semantically (and functionally, since it uses universal newlines and omits a trailing empty line) better than split('\n'). Back then (2008) I was just a newbie Pythonista and grepping though my scripts now shows that I too am using splitlines() almost exclusively. I'm therefore deleting my 104-point answer (_*sob...*_) and will be endorsing this one instead. – efotinis Aug 28 '14 at 09:52
  • 19
    This also makes `''.splitlines() == []`, not `['']` as with `''.split('\n')`. –  Sep 30 '14 at 09:50
202
inputString.split('\n')  # --> ['Line 1', 'Line 2', 'Line 3']

This is identical to the above, but the string module's functions are deprecated and should be avoided:

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

Alternatively, if you want each line to include the break sequence (CR,LF,CRLF), use the splitlines method with a True argument:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
efotinis
  • 14,565
  • 6
  • 31
  • 36
  • 12
    This will only work on systems that use '\n' as the line terminator. – Jeremy Cantrell Oct 06 '08 at 14:46
  • 20
    @Jeremy: Triple-quoted string literals always use a '\n' EOL, regardless of platform. So do files read in text mode. – efotinis Oct 06 '08 at 16:55
  • 4
    link to the method: http://docs.python.org/2/library/stdtypes.html#str.splitlines –  May 25 '13 at 17:42
  • 16
    `inputString.split(os.linesep)` will use the platform specific line terminator. – James Jun 18 '13 at 12:18
  • 12
    It is strange that this answer is so upvoted. Hard coding '\n' is a bad idea, but even if you use os.linesep instead of that, you will have issues with windows line ends on Linux and vice versa, etc. Moreover, it is promoting splitlines with True argument which is likely the less common way of using it... – László Papp Aug 27 '14 at 17:29
  • 6
    A combination of a suboptimal method, a deprecated method, and a redundant variation of the optimal method. – jwg Jan 08 '15 at 14:06
  • 4
    The best way is probably with `splitlines`. `os.linesep` is a plain old mistake, much worse than `'\n'`. If you are on Windows, you might still get Unix text. Then your lines will not be split. If you use `'\n'` on Windows text, then worst that happens is you get spurious `\r` characters that can be cleaned up with `.strip()` -- which you usually want to call anyway. – Adrian Ratnapala Aug 30 '15 at 16:26
61

Use inputString.splitlines().


Why splitlines is better

splitlines handles newlines properly, unlike split.

It also can optionally return the newline character in the split result when called with a True argument, which is useful in some specific scenarios.


Why you should NOT use split("\n")

Using split creates very confusing bugs when sharing files across operating systems.

\n in Python represents a Unix line-break (ASCII decimal code 10), independently of the OS where you run it. However, the ASCII linebreak representation is OS-dependent.

On Windows, \n is two characters, CR and LF (ASCII decimal codes 13 and 10, \r and \n), while on modern Unix (Mac OS X, Linux, Android), it's the single character LF.

print works correctly even if you have a string with line endings that don't match your platform:

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

However, explicitly splitting on "\n", has OS-dependent behaviour:

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

Even if you use os.linesep, it will only split according to the newline separator on your platform, and will fail if you're processing text created in other platforms, or with a bare \n:

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

splitlines solves all these problems:

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

Reading files in text mode partially mitigates the newline representation problem, as it converts Python's \n into the platform's newline representation.

However, text mode only exists on Windows. On Unix systems, all files are opened in binary mode, so using split('\n') in a UNIX system with a Windows file will lead to undesired behavior. This can also happen when transferring files in the network.

loopbackbee
  • 21,962
  • 10
  • 62
  • 97
  • The comparison is not fair because you could use split(os.linesep), too, to avoid the platform specific bit. – László Papp Aug 27 '14 at 15:28
  • 6
    @lpapp note that `splitlines` will split on *any* line ending. `split(os.linesep)` will fail when reading a windows file in unix, for example – loopbackbee Aug 27 '14 at 17:19
  • 1
    Another reason for using splitlines in my case, thanks. I gave a +1. I would personally even incorporate the information in comments into your answer. – László Papp Aug 27 '14 at 17:25
21

Might be overkill in this particular case but another option involves using StringIO to create a file-like object

for line in StringIO.StringIO(inputString):
    doStuff()
iruvar
  • 22,736
  • 7
  • 53
  • 82
0

I would like to augment @1_CR 's answer: He led me to the following technique; it will use cStringIO if available (BUT NOTE: cStringIO and StringIO are not the same, because you cannot subclass cStringIO... it is a built-in... but for basic operations the syntax will be identical, so you can do this):

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

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Mike S
  • 1,235
  • 12
  • 19
0

The original post requested for code which prints some rows (if they are true for some condition) plus the following row. My implementation would be this:

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
  • 1,231
  • 2
  • 14
  • 18
0

in Python3 use this code

from io import StringIO
for sline in sio.readlines():
        print(sline)