Credit: Tom Good
You have a string made up of multiple lines, and you need to build another string from it, adding or removing leading spaces on each line so that the indentation of each line is some absolute number of spaces.
We
don’t need re
for this. The
string
module (or string methods, in Python 2.0
and later) is quite sufficient:
import string def reindent(s, numSpaces): s = string.split(s, '\n') s = [(numSpaces * ' ') + string.lstrip(line) for line in s] s = string.join(s, '\n') return s
When working with text, it may be necessary to change the indentation level of a block. This recipe’s code takes a multiline string and adds or removes leading spaces on each line so that the indentation level of each line of the block matches some absolute number of spaces. For example:
>>> x = """line one ... line two ... and line three ... """ >>> print x line one line two and line three >>> print reindent(x, 8) line one line two and line three
Even if the lines in s
are initially indented
differently, this recipe makes their indentation homogeneous. This is
sometimes what we want, and sometimes not. A frequent need is to
adjust the amount of leading spaces in each line, so that the
relative indentation of each line in the block is preserved. This is
not hard either, for either positive or negative values of the
adjustment. However, negative values need a check to ensure that no
nonspaces are snipped from the start of the lines. Thus, we may as
well split the functionality into two functions to perform the
transformations, plus one to measure the number of leading spaces of
each line and return the result as a
list:
def addSpaces(s, numAdd): white = " "*numAdd return white + white.join(s.splitlines(1)) def delSpaces(s, numDel): def aux(line, numDel=numDel, white=" "*numDel): if line[:numDel] != white: raise ValueError, "removing more spaces than there are!" return line[numDel:] return ''.join(map(aux, s.splitlines(1))) def numSpaces(s): return [len(line)-len(line.lstrip()) for line in s.splitlines( )]
This alternative approach relies on the string method
splitlines
(and so requires Python 2.0 or later, like any other recipe using
string methods and/or list comprehensions), which is similar to a
split on '\n'
, with the extra ability to leave the
trailing newline on each line when called with a true argument. This
is not often crucial (the last statement in
delSpaces
, for example, might just as easily
return '\n'.join(map(aux, s.split('\n')))
), but
sometimes it turns out to be (addSpaces
could not
be quite as short and sweet without this ability of the
splitlines
string method).
For example, here’s how we can combine these functions to build another function that deletes enough leading spaces from each line to ensure that the least-indented line of the block becomes flush-left, while preserving the relative indentations of all the other lines:
def unIndentBlock(s): return delSpaces(s, min(numSpaces(s)))
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.