Python中如何按照前缀最短空格缩进处理多行文本

假设有这样一个文本

    1234
      123456
        12345678
    1234

我想要按照前缀最短空格缩进,即上述文本最短空格为 4 ,就把整个文本都向左缩进 4 个空格

目前想到的方法是先遍历一遍,找出最短空格,再遍历一遍,逐行缩进,请教一下还有更好的方法吗?


Python中如何按照前缀最短空格缩进处理多行文本
7 回复

基本上就是这个思路,没法再更简单了。


import re

def indent_by_shortest_prefix(text):
    """
    按照前缀最短空格缩进处理多行文本
    
    原理:
    1. 找出所有非空行的最小公共前缀空格数
    2. 每行都减去这个最小空格数
    3. 保留空行的原始状态
    """
    if not text:
        return text
    
    lines = text.splitlines()
    
    # 找出所有非空行的前导空格数
    leading_spaces = []
    for line in lines:
        if line.strip():  # 非空行
            match = re.match(r'^(\s*)', line)
            if match:
                leading_spaces.append(len(match.group(1)))
    
    if not leading_spaces:  # 全是空行
        return text
    
    # 计算最小缩进
    min_indent = min(leading_spaces)
    
    # 重新构建文本
    result_lines = []
    for line in lines:
        if line.strip() and len(line) >= min_indent:
            # 非空行且长度足够,去除最小缩进
            result_lines.append(line[min_indent:])
        else:
            # 空行或长度不足,保持原样
            result_lines.append(line)
    
    return '\n'.join(result_lines)


# 测试示例
if __name__ == "__main__":
    # 示例1:常规缩进
    text1 = """    def hello():
        print("Hello")
        if True:
            print("World")
    
    def goodbye():
        print("Goodbye")"""
    
    print("原始文本1:")
    print(text1)
    print("\n处理结果1:")
    print(indent_by_shortest_prefix(text1))
    
    # 示例2:混合缩进
    text2 = """  line1
        line2
          line3
    line4"""
    
    print("\n\n原始文本2:")
    print(text2)
    print("\n处理结果2:")
    print(indent_by_shortest_prefix(text2))
    
    # 示例3:有空行
    text3 = """    first line
    
        second line
          third line"""
    
    print("\n\n原始文本3:")
    print(text3)
    print("\n处理结果3:")
    print(indent_by_shortest_prefix(text3))

这个函数的工作原理:

  1. 首先找出所有非空行的前导空格数量
  2. 计算这些空格数的最小值
  3. 对每行文本,如果是非空行就减去这个最小空格数
  4. 空行保持原样不处理

关键点:

  • 使用正则表达式 r'^(\s*)' 匹配每行开头的空格
  • line.strip() 判断是否为空行(包含空白字符的行)
  • 空行不参与最小缩进的计算,保持原样输出

测试用例展示了不同情况:

  • 统一缩进的代码块
  • 混合缩进的文本
  • 包含空行的文本

处理后的文本会保持原有的相对缩进关系,只是整体向左移动,使最小缩进变为0。

一句话总结:找出最小公共缩进并整体左移。

楼主要是会 vi 的话,这就是 3 s 的问题
区块操作 瞬间完成,没法细说

会 vi,但我需要使用程序进行处理,另外我记得 vi 貌似也没这个功能

  1. 首先确认 最短几个空格,比如 3 个
    2. :%s/^_ *//g (祛除所以开头空格,下划线 表示一个空格的意思,注意)
    3. :%/^/___/g (所有开开头加 3 个空格)


    三秒解决问题

先确认最短几个空格? 就是这一步也不只 3s 了吧

嗯,你是对的

回到顶部