How to split in such a way that "\n" is also a new element in python?

Viewed 72

I have a big string where there are multiple lines. For example,

abc def
ghi hij

When I do .split() with the above string, I get as follows:

['abc', 'def\n', 'ghi', 'hih']

The output I want is,

['abc', 'def', '\n', 'ghi', 'hih']

There can be cases where .split() leads to:-

['abc', '\n', 'dsa\n\n\nkij', 'poi']

I want this actually as follow:

['abc', '\n', 'dsa', '\n', '\n', '\n', 'kij', 'poi']

I would like to have a simple python code.

3 Answers

You could use a regular expression split: re.split

>>> a = 'abc def\nghi   hij\n\n\nsdf ste'

>>> re.split(r" +|(?=\n)|(?<=\n)", a)
['abc', 'def', '\n', 'ghi', 'hij', '\n', '\n', '\n', 'sdf', 'ste']

The regular expression that this is using says to split either on one or more spaces, or if the next or previous character is a newline (using lookahead and lookbehind assertions).

You can write a much simpler regex for this using groups and .findall(), which will return a list of all matches from a source string for you

>>> src = """abc def
... ghi hij
... """
>>> re.findall(r"([^ \n]+|\n)", src)
['abc', 'def', '\n', 'ghi', 'hij', '\n']
>>> src = "".join(['abc', '\n', 'dsa\n\n\nkij', 'poi'])
>>> print(src)
abc
dsa


kijpoi
>>> re.findall(r"([^ \n]+|\n)", src)
['abc', '\n', 'dsa', '\n', '\n', '\n', 'kijpoi']

This works by finding every block of either

  • greedy ranges of not space or \n (anything until one is found; this is an opportunity to include more characters like \t or to use \s, which is any "whitespace character")
  • exactly \n

You could potentially also use .finditer() to make more efficient use in some generator, though it's likely to make your solution more complex

You can use re.split() with lookarounds for \n:

import re
print(re.split(r'(?<=\n)(?!$)|(?<!^)(?=\n)| ', your_str))
Related