如何删除Python三引号多行字符串的额外缩进?

时间:2009-09-11 17:51:05

标签: python quotes multiline

我有一个python编辑器,用户输入一个脚本或代码,然后将其放入幕后的main方法中,同时每行都缩进。问题是如果用户有多行字符串,则通过在每个空格中插入制表符,对整个脚本的缩进会影响字符串。问题脚本将是如此简单:

"""foo
bar
foo2"""

因此,在主方法中,它看起来像:

def main():
    """foo
    bar
    foo2"""

并且字符串现在在每行的开头都有一个额外的标签。

7 个答案:

答案 0 :(得分:99)

来自标准库的

textwrap.dedent可以自动撤消古怪的缩进。

答案 1 :(得分:24)

从我看到的情况来看,这里更好的答案可能是inspect.cleandoc,它在功能上与textwrap.dedent的作用相同,但也解决了textwrap.dedent与引导线的问题。以下示例显示了差异:

   >>> import textwrap
   >>> import inspect
   >>> x = """foo bar
       baz
       foobar
       foobaz
       """
   >>> inspect.cleandoc(x)
   'foo bar\nbaz\nfoobar\nfoobaz'
   >>> textwrap.dedent(x)
   'foo bar\n    baz\n    foobar\n    foobaz\n'
   >>> y = """
   ...     foo
   ...     bar
   ... """
   >>> textwrap.dedent(y)
   '\nfoo\nbar\n'
   >>> inspect.cleandoc(y)
   'foo\nbar'

答案 2 :(得分:16)

多行字符串的第一行后面的内容是字符串的一部分,并且不被解析器视为缩进。你可以随意写:

def main():
    """foo
bar
foo2"""
    pass

它会做正确的事。

另一方面,这是不可读的,Python知道它。因此,如果docstring在其 second 行中包含空格,那么当您使用help()查看文档字符串时,会删除该数量的空白。因此,help(main)和以下help(main2)会生成相同的帮助信息。

def main2():
    """foo
    bar
    foo2"""
    pass

答案 3 :(得分:1)

我看到的唯一方法是从第二行开始为每行删除前n个制表符,其中n是main方法的已知标识。

如果事先不知道该标识 - 您可以在插入之前添加尾随换行符,并从最后一行删除标签数量...

第三个解决方案是解析数据并查找多行引用的开头,并且在关闭之前不要将您的标识添加到每一行。

认为有更好的解决方案..

答案 4 :(得分:1)

我想保留三引号行之间的内容,仅删除常见的前导缩进。我发现 texwrap.dedentinspect.cleandoc 做得不太对,所以我写了这个。它使用 os.path.commonprefix

import re
from os.path import commonprefix

def ql(s, eol=True):
    lines = s.splitlines()
    l0 = None
    if lines:
        l0 = lines.pop(0) or None
    common = commonprefix(lines)
    indent = re.match(r'\s*', common)[0]
    n = len(indent)
    lines2 = [l[n:] for l in lines]
    if not eol and lines2 and not lines2[-1]:
        lines2.pop()
    if l0 is not None:
        lines2.insert(0, l0)
    s2 = "\n".join(lines2)
    return s2

这可以引用任何缩进的字符串。我希望它默认包含尾随换行符,但可以选择删除它,以便它可以整齐地引用任何字符串。

示例:

print(ql("""
     Hello
    |\---/|
    | o_o |
     \_^_/
    """))

print(ql("""
         World
        |\---/|
        | o_o |
         \_^_/
    """))

第二个字符串有 4 个通用缩进空格,因为最后的 """ 缩进小于引用的文本:

 Hello
|\---/|
| o_o |
 \_^_/

     World
    |\---/|
    | o_o |
     \_^_/

我认为这会更简单,否则我不会为此烦恼!

答案 5 :(得分:0)

更加清楚地显示textwrap.dedentinspect.cleandoc之间的区别:

行为没有缩进的行为

import textwrap
import inspect

string1="""String
with
no indentation
       """
string2="""String
        with
        indentation
       """
print('string1 plain=' + repr(string1))
print('string1 inspect.cleandoc=' + repr(inspect.cleandoc(string1)))
print('string1 texwrap.dedent=' + repr(textwrap.dedent(string1)))
print('string2 plain=' + repr(string2))
print('string2 inspect.cleandoc=' + repr(inspect.cleandoc(string2)))
print('string2 texwrap.dedent=' + repr(textwrap.dedent(string2)))

输出

string1 plain='String\nwith\nno indentation\n       '
string1 inspect.cleandoc='String\nwith\nno indentation\n       '
string1 texwrap.dedent='String\nwith\nno indentation\n'
string2 plain='String\n        with\n        indentation\n       '
string2 inspect.cleandoc='String\nwith\nindentation'
string2 texwrap.dedent='String\n        with\n        indentation\n'

前导部分缩进的行为

string1="""
String
with
no indentation
       """
string2="""
        String
        with
        indentation
       """

print('string1 plain=' + repr(string1))
print('string1 inspect.cleandoc=' + repr(inspect.cleandoc(string1)))
print('string1 texwrap.dedent=' + repr(textwrap.dedent(string1)))
print('string2 plain=' + repr(string2))
print('string2 inspect.cleandoc=' + repr(inspect.cleandoc(string2)))
print('string2 texwrap.dedent=' + repr(textwrap.dedent(string2)))

输出

string1 plain='\nString\nwith\nno indentation\n       '
string1 inspect.cleandoc='String\nwith\nno indentation\n       '
string1 texwrap.dedent='\nString\nwith\nno indentation\n'
string2 plain='\n        String\n        with\n        indentation\n       '
string2 inspect.cleandoc='String\nwith\nindentation'
string2 texwrap.dedent='\nString\nwith\nindentation\n'

答案 6 :(得分:-3)

因此,如果我正确理解,您可以接受用户输入的任何内容,将其缩进并将其添加到程序的其余部分(然后运行整个程序)。

因此,在将用户输入放入程序后,您可以运行正则表达式,基本上将强制缩进恢复。类似于:在三个引号内,替换所有“新行标记”,后跟四个空格(或制表符),只有一个“新行标记”。