58

私が文字列を持っているとしましょう

s = """
    Controller = require 'controller'

    class foo
        view: 'baz'
        class: 'bar'

        constructor: ->
            Controller.mix @
"""

文字列のすべての行に、グローバルな 4 スペースのインデントが追加されました。この文字列が関数内で宣言されている場合、8 スペースのグローバル インデントなどがあります。

Python には、文字列のグローバルな左インデントを削除する機能がありますか?

その関数の出力を次のようにしたいと思います。

Controller = require 'controller'

class foo
    view: 'baz'
    class: 'bar'

    constructor: ->
        Controller.mix @"
4

4 に答える 4

105

組み込み関数ではなく、標準ライブラリの関数: textwrap.dedent()

>>> print(textwrap.dedent(s))

Controller = require 'controller'

class foo
    view: 'baz'
    class: 'bar'

    constructor: ->
        Controller.mix @
于 2012-06-22T13:24:35.153 に答える
9

textwrap.dedent()必要なものに近いですが、先頭に改行があるため、要求したものを実装していません。dedentから先頭の改行を取り除く関数でラップすることができますs

def my_dedent(string):
    if string and string[0] == '\n':
        string = string[1:]
    return textwrap.dedent(string)

ただしtextwrap.dedent()、末尾の空白が重要でない複数行のインデント ステートメントから Python ソースを生成する場合は、特別な方法で空白だけの行を処理します。

しかし、一般にtextwrap.dedent()、「最大インデント」よりも多くの空白を含む行から余分な空白を削除すること、すべての空白行から空白を削除すること、および最後の空白の前に空白を破棄する"""ことは不適切です。正規表現

また、スペースがしばしば重要な Python 以外のソース コードも生成するため、次のルーチンを使用します。TAB のインデントは処理しませんが、textwrap.dedent()失敗した場合、先頭の改行なしで要求した出力が得られます。

def remove_leading_spaces(s, strict=False):
    '''Remove the maximum common spaces from all non-empty lines in string

Typically used to remove leading spaces from all non-empty lines in a
multiline string, preserving all extra spaces.
A leading newline (when not useing '"""\') is removed unless the strict
argument is True.

Note that if you want two spaces on the last line of the return value 
without a newline, you have to use the max indentation + 2 spaces before 
the closing """. If you just input 2 spaces that is likely to be the 
maximum indent.
    '''
    if s and not strict and s[0] == '\n':
        s = s[1:]
    lines = s.splitlines(True) # keep ends
    max_spaces = -1
    for line in lines:
        if line != '\n':
            for idx, c in enumerate(line[:max_spaces]):
                if not c == ' ':
                    break
            max_spaces = idx + 1
    return ''.join([l if l == '\n' else l[max_spaces-1:] for l in lines])
于 2013-03-17T12:55:09.593 に答える