Python:除了保留换行符之外,首先缩进字符串的所有行?

时间:2013-08-29 18:04:55

标签: python string text indentation textwrapping

我想缩小除第一行之外的多行字符串的所有行,而不包装文本。

例如,我想转:

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

成:

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

我试过了

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

但这仍然将所有文字放在一行。想法?

3 个答案:

答案 0 :(得分:14)

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

string = string.replace('\n', '\n    ')

答案 1 :(得分: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

答案 2 :(得分: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倍慢。

Python 3将indent添加到textwrap,这使得缩进而不重新包装非常容易。肯定有一种处理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