9

I want to indent all lines of a multi-line string except the first, without wrapping the text.

For example, I want to turn:

A very very very very very very very very very very very very very very very very
long mutiline
string

into:

A very very very very very very very very very very very very very very very very
     long multiline
     string

I have tried

textwrap.fill(string, width=999999999999, subsequent_indent='   ',)

But this still puts all of the text on one line. Thoughts?

4

3 回答 3

16

您只需要用换行符'\n'加上空格替换换行符 '\n    '并将其保存到变量中(因为replace不会更改原始字符串,但会返回带有替换的新字符串)。

string = string.replace('\n', '\n    ')
于 2013-08-29T18:29:39.350 回答
2

你的意思是这样的:

In [21]: s = 'abc\ndef\nxyz'

In [22]: print s
abc
def
xyz

In [23]: print '\n    '.join(s.split('\n'))
abc
    def
    xyz

?

编辑:或者(HT @Steven Rumbalski):

In [24]: print s.replace('\n', '\n    ')
abc
    def
    xyz
于 2013-08-29T18:16:28.213 回答
0

@steven-rumbalski提到的裸替换将是实现此目的的最有效方法,但这不是唯一的方法。

这是使用列表推导的另一种解决方案。如果文本已经被分割成行列表,这将比运行快得多join()replace()并且splitlines()

text = """A very very very very very very very very very very very very very very very very
long mutiline
string"""

lines = text.splitlines()
indented = ['    ' + l for l in lines]
indented[0] = lines[0]
indented = '\n'.join(indented)

该列表可以就地修改,但与使用第二个变量相比,性能成本很高。缩进所有行然后在另一个操作中换出第一行也比较快。

还有textwrap模块。我不同意使用 textwrap 进行缩进是 unpythonic 的。如果这些行连接在一个包含换行符的字符串中,则该字符串本质上是换行的。缩进是文本换行的逻辑扩展,所以 textwrap 对我来说很有意义。

除了它很慢。真的,真的很慢。就像慢了 15 倍。

indent添加的Python 3textwrap使得无需重新包装的缩进变得非常容易。当然有一种更优雅的方式来处理 lambda 谓词,但这正是原始问题所要求的。

indented = textwrap.indent(text, '    ', lambda x: not text.splitlines()[0] in x )

timeit以下是各种方法的一些结果。

>>> timeit.timeit(r"text.replace('\n', '\n    ')", setup='text = """%s"""' % text)
0.5123521030182019

两个列表理解解决方案:

>>> timeit.timeit(r"indented = ['    ' + i for i in lines]; indented[0] = lines[0]", setup='lines = """%s""".splitlines()' % text)
0.7037646849639714

>>> timeit.timeit(r"indented = [lines[0]] + ['    ' + i for i in lines[1:]]", setup='lines = """%s""".splitlines()' % text)
1.0310905870283023

这是不幸的textwrap结果:

>>> timeit.timeit(r"textwrap.indent(text, '    ', lambda x: not text.splitlines()[0] in x )", setup='import textwrap; text = """%s"""' % text)
7.7950868209591135

我认为其中一些时间可能是非常低效的谓词,但即使将其删除,textwrap.indent它仍然比裸替换慢 8 倍以上。

>>> timeit.timeit(r"textwrap.indent(text, '    ')", setup='import textwrap; text = """%s"""' % text)
4.266149697010405
于 2013-11-23T04:11:05.833 回答