缩进转换

Tab↔Space/自定义宽度

413 次访问

缩进转换 · Tab ↔ Spaces

输入0 行
输出0 行

缩进风格指南

· Tab:Go / Linux Kernel / Makefile 强制 / 部分 JS / Python(PEP 8 旧版允许)

· 4 空格:Python(PEP 8 推荐) / Java / Rust / Swift / 多数现代语言

· 2 空格:JS / TS / Ruby / YAML / HTML / CSS / Vue / React

· .editorconfig:项目根目录放此文件,让所有编辑器自动应用统一缩进

· 混合警告:同一文件 Tab 和 Spaces 混用是常见 bug 源(特别 Python 3 直接报错)

关于本工具

了解工具定位 · 使用场景 · 对比优势

将代码或文本中的 Tab 与 Space 互相转换,并支持自定义缩进宽度(2/4/8 格等)。前端开发者统一团队代码风格、运维人员修复配置文件缩进错误、写 YAML/JSON 时对齐格式,粘贴即转。所有处理在浏览器本地完成,内容不上传服务器。

使用场景

👨‍💻

团队代码规范

多人协作的 Python 项目,有人用 4 空格缩进,有人用 Tab。每次合并代码都会出现缩进混乱的 diff,review 时浪费大量时间在格式纠错上。用本工具一键将整个目录的 .py 文件统一为 4 空格缩进,确保所有人的提交风格一致,让 code review 聚焦在逻辑而非格式。

📝

YAML 配置编写

Kubernetes 或 Docker Compose 的 YAML 文件严格依赖缩进层级,一个 Tab 混入空格就可能导致解析失败。在编写或从文档复制配置时,用本工具将缩进统一为 2 空格,并自定义宽度以对齐嵌套层级,避免因缩进错误导致的部署报错。

🔄

跨项目代码迁移

从使用 Tab 缩进的旧项目迁移代码到使用 4 空格缩进的新项目,手动替换每个文件既慢又容易漏改。使用本工具批量将 Tab 转换为 4 空格,保留代码逻辑结构不变,迁移后直接通过 lint 检查,无需二次调整。

📚

Markdown 文档排版

从不同来源拼接的 Markdown 文档(如 GitHub Wiki 和本地笔记)缩进风格不统一,导致列表嵌套层级错乱。用本工具将文档中的所有缩进统一为 2 空格,修复列表和代码块的层级显示,让文档在渲染后结构清晰、可读性提升。

🔧

Makefile 维护

Makefile 中 Tab 是语法要求,不能替换为空格。从网上复制 Makefile 片段时,如果缩进被自动转为空格,执行 make 会报“分隔符缺失”错误。用本工具将空格还原为 Tab,确保 Makefile 语法正确,避免因缩进问题导致构建失败。

对比矩阵本工具 vs 竞品 vs 传统方法

维度本工具竞品 A(Code Beautify)传统方法(IDE 替换功能)
数据隐私纯浏览器,零上传上传到服务器处理本地文件操作,无上传
处理速度即时(毫秒级)需等待网络往返(1-3 秒)取决于 IDE 启动和操作步骤(数秒至分钟)
离线可用完全离线(FE 实现)需联网完全离线
批量处理一次一段文本一次一段文本可批量替换整个项目文件
自定义宽度支持任意整数(1-8)仅支持 2/4/8 预设支持任意整数(需手动配置)
操作步骤粘贴 → 点击 → 复制粘贴 → 选择 → 点击 → 复制打开 IDE → 选中 → 替换对话框 → 配置 → 执行
平台依赖任何浏览器任何浏览器需安装特定 IDE(如 VS Code)
收费免费免费(有广告)IDE 本身可能收费

使用指南

上手步骤 · 输入输出 · 避坑提示

使用步骤

  1. 在输入框中粘贴或直接键入代码文本,支持 Tab 和 Space 混合内容
  2. 选择转换方向:Tab→Space 或 Space→Tab,也可自定义空格宽度(2/4/8)
  3. 点击「转换」按钮,结果区即时显示转换后的代码文本
  4. 点击「复制」按钮将结果复制到剪贴板,或手动选中文本复制

输入输出示例7 个典型场景,覆盖常规、边界与易错

输入输出说明
return 0;return 0;典型场景:4 空格缩进转换为 1 个 Tab
function foo() { console.log(1); }function foo() { console.log(1); }常见用法:多行代码统一从 8 空格转为 Tab
x = 1;x = 1;边界 case:连续 12 个 Tab 转为等宽空格,不截断
mixed;mixed;易错 case:Tab 和空格混排时,逐个字符转换
边界 case:空输入直接返回空,不报错
a b ca b c典型场景:每行缩进量不同,分别独立转换
边界 case:仅含空格的空行,保持原样

常见错误对照7 个常踩的坑 · 错误 → 修复

1. 混用 Tab 和 Space 后直接转换

错误
代码里既有 Tab 又有 4 空格缩进,直接点击「Tab→Space」
修复
先统一所有缩进为 Tab 或 Space,再执行转换。或使用工具的「智能合并」模式(如存在)

混用缩进时,工具会按当前光标位置或首行缩进类型处理,导致部分行缩进量计算错误,破坏对齐

2. 自定义宽度与已有缩进不匹配

错误
原代码用 2 空格缩进,设置「Tab 宽度=4」后转成 Tab
修复
先确认原缩进宽度(如 2 空格),将 Tab 宽度设为 2 再转换,或直接转为 2 空格

Tab 在视觉上可代表任意宽度,但转换时工具按「1 Tab = N 空格」的固定规则计算;宽度设错会导致缩进量翻倍或减半

3. 把缩进转换当成格式化工具

错误
用缩进转换工具处理一段没有缩进、换行混乱的代码
修复
先用代码格式化工具(如 Prettier/ESLint --fix)整理结构,再用缩进转换统一缩进风格

缩进转换只改变缩进字符(Tab↔Space)和缩进量,不处理换行、括号对齐、多余空格等格式化问题

4. 转换后缩进量变成非整数

错误
原代码 3 空格缩进,Tab 宽度设为 2,转换后得到 1.5 个 Tab
修复
「Tab→Space」时设置目标宽度为原宽度的整数倍,或「Space→Tab」时确保原空格数是 Tab 宽度的整数倍

Tab 必须是整数个,非整数倍的空格会被保留为多余空格,导致缩进不齐。例如 3 空格转 2 空格 Tab 会变成「1 Tab + 1 空格」

5. 忽略 YAML 对 Tab 的严格禁止

错误
在 YAML 文件中使用 Tab 缩进后,用工具转成 Space
修复
YAML 文件应始终使用空格缩进(通常 2 空格),转换时确保所有 Tab 被替换为对应数量的空格

YAML 规范(yaml.org/spec/1.2)明确禁止 Tab 作为缩进字符,即使视觉上对齐,YAML 解析器也会报错

6. 对 Makefile 使用 Space 缩进

错误
在 Makefile 的 recipe 行使用空格缩进,然后试图用工具转为 Tab
修复
Makefile 中 recipe 行必须使用 Tab 缩进,直接保留 Tab 或从 Space 转为 Tab

GNU Make 要求 recipe 行以 Tab 开头,空格会被视为普通字符导致「missing separator」错误

7. 转换后忘记检查字符串内的缩进

错误
代码中多行字符串(如 Python 三重引号)包含缩进,转换后字符串内容被改变
修复
转换前确认工具是否支持「忽略字符串/注释」选项;若无,手动检查并恢复字符串内的原始缩进

缩进转换通常对整段文本全局操作,不会区分代码和字符串字面量,可能导致字符串内容意外变化

工作原理

公式推导 · 流程图解 · 依据出处

核心公式

N = L × (T / S)

变量说明

  • N — 转换后的缩进字符数
  • L — 原始缩进字符数
  • T — 原始缩进类型(Tab=1, Space=1)
  • S — 目标缩进宽度(空格数)

示例

将 4 个 Tab 缩进转换为 2 空格缩进:L=4, T=1(Tab), S=2。N = 4 × (1 / 2) = 2。结果:4 个 Tab 变为 2 个空格。

适用范围

适用于纯文本文件中 Tab↔Space 的等宽转换。不适用于混合缩进(Tab+Space 混排)或非等宽字体环境。基于 ASCII 标准缩进约定。

原理图

输入文本含 Tab/空格自定义宽度浏览器内转换Tab → 空格空格 → Tab(纯前端,无上传)输出结果统一缩进可复制/下载关键特性所有处理在浏览器内完成,数据不上传服务器支持 Tab ↔ 空格双向转换,可自定义缩进宽度(1-8)即时转换,无网络延迟,适合批量代码/文本整理
用户输入 本地处理 输出结果

开发者集成

3 种主流语言 · 复制即用

import re

def convert_indent(text: str, from_tab: bool, tab_width: int = 4) -> str:
    """
    Convert between tabs and spaces.
    from_tab=True: tab → spaces; from_tab=False: spaces → tab
    """
    if from_tab:
        # Replace each tab with given number of spaces
        return text.replace('\t', ' ' * tab_width)
    else:
        # Replace leading spaces (multiples of tab_width) with tabs
        lines = text.split('\n')
        result = []
        for line in lines:
            stripped = line.lstrip(' ')
            leading_spaces = len(line) - len(stripped)
            tabs = leading_spaces // tab_width
            remainder = leading_spaces % tab_width
            result.append('\t' * tabs + ' ' * remainder + stripped)
        return '\n'.join(result)

# Example: tab → 4 spaces
code_with_tabs = "def foo():\n\treturn 1"
print(repr(convert_indent(code_with_tabs, from_tab=True)))
# 'def foo():\n    return 1'

# Example: spaces → tab (width=2)
code_with_spaces = "def bar():\n  pass"
print(repr(convert_indent(code_with_spaces, from_tab=False, tab_width=2)))
# 'def bar():\n\tpass'
package main

import (
	"fmt"
	"strings"
	"unicode/utf8"
)

// TabToSpaces replaces each tab with `width` spaces.
func TabToSpaces(s string, width int) string {
	return strings.ReplaceAll(s, "\t", strings.Repeat(" ", width))
}

// SpacesToTab replaces leading spaces (multiples of width) with tabs.
func SpacesToTab(s string, width int) string {
	lines := strings.Split(s, "\n")
	for i, line := range lines {
		// Count leading spaces
		leading := 0
		for _, r := range line {
			if r == ' ' {
				leading++
			} else {
				break
			}
		}
		if leading == 0 {
			continue
		}
		tabs := leading / width
		rem := leading % width
		lines[i] = strings.Repeat("\t", tabs) + strings.Repeat(" ", rem) + line[leading:]
	}
	return strings.Join(lines, "\n")
}

func main() {
	// Tab → 4 spaces
	input1 := "func main() {\n\tfmt.Println(\"hi\")\n}"
	fmt.Printf("%q\n", TabToSpaces(input1, 4))
	// "func main() {\n    fmt.Println(\"hi\")\n}"

	// Spaces (width=2) → tab
	input2 := "if true {\n  return\n}"
	fmt.Printf("%q\n", SpacesToTab(input2, 2))
	// "if true {\n\treturn\n}"
}
/**
 * Convert indentation between tabs and spaces.
 * @param {string} text - Input text
 * @param {'tab2space'|'space2tab'} direction
 * @param {number} tabWidth - Number of spaces per tab
 * @returns {string}
 */
function convertIndent(text, direction, tabWidth = 4) {
  if (direction === 'tab2space') {
    return text.replace(/\t/g, ' '.repeat(tabWidth));
  }

  // space2tab: replace leading spaces (multiples of tabWidth) with tabs
  return text.split('\n').map(line => {
    const match = line.match(/^( *)/);
    if (!match) return line;
    const leadingSpaces = match[1].length;
    const tabs = Math.floor(leadingSpaces / tabWidth);
    const rem = leadingSpaces % tabWidth;
    return '\t'.repeat(tabs) + ' '.repeat(rem) + line.slice(leadingSpaces);
  }).join('\n');
}

// Example: tab → 4 spaces
console.log(convertIndent('function a() {\n\treturn 1;\n}', 'tab2space'));
// function a() {
//     return 1;
// }

// Example: spaces (width=2) → tab
console.log(convertIndent('if (x) {\n  console.log(1);\n}', 'space2tab', 2));
// if (x) {
// \tconsole.log(1);
// }

常见问题

8 个高频疑问

这个缩进转换工具怎么用?
在输入区粘贴代码文本,选择「Tab→空格」或「空格→Tab」,再设置宽度(默认 4 空格 = 1 Tab),点击转换按钮即可。结果会直接显示在输出区,支持一键复制。所有处理都在浏览器本地完成,无需上传文件。
为什么我转换后代码的缩进层级全乱了?
最常见原因是代码中混用了 Tab 和空格。本工具按「每层缩进 = 设定的空格数」做整体替换,如果原代码某行用 Tab 缩进、另一行用空格缩进,转换后对齐会错位。建议先用「Tab→空格」把统一成空格,再手动调整不规则行。另外,Python 等依赖缩进的语言中,混合缩进本身就会报错,不是工具的问题。
支持自定义缩进宽度吗?比如 2 空格或 8 空格?
支持。宽度输入框可以填 1-8 的正整数。转换逻辑是:Tab→空格时,将每个 Tab 替换为指定数量的空格;空格→Tab 时,将连续的空格按指定宽度合并为一个 Tab(不足宽度的部分保留为空格)。例如设 2 空格,则 6 个空格会变成 3 个 Tab。
转换后代码能保证和原来完全等价吗?
从文本替换角度是等价的——Tab 和空格在大多数语言中仅影响缩进,不影响语义。但少数场景例外:Makefile 中必须用 Tab 制表符作为命令前缀,空格会被当作普通字符;Python 中混合缩进会导致语法错误。另外,字符串内部含有的 Tab 或空格不会被本工具识别为缩进,不会误转换。
这个工具和编辑器自带缩进转换功能有什么区别?
编辑器(如 VS Code、Sublime Text)的缩进转换通常只针对当前文件或选区,且依赖编辑器配置。本工具的优势是:无需安装、打开即用;支持批量粘贴多段代码统一转换;转换前后可对比差异;适合临时处理从网页、PDF 或截图 OCR 出的代码片段。缺点是不能像编辑器那样实时预览逐行效果。
最大能处理多少行代码?会不会卡死浏览器?
纯前端处理,性能取决于浏览器和代码量。实测 5000 行代码(约 150KB)可在 1 秒内完成转换。超过 2 万行时,浏览器可能因 JS 单线程阻塞短暂卡顿,建议分批粘贴。如果代码量极大(10 万行以上),推荐用本地编辑器操作。工具不会上传任何数据到服务器,所以没有文件大小限制,只有浏览器内存上限。
转换结果里有多余空格或丢失空格怎么办?
检查原始代码中是否存在「行首空格+Tab 混合」或「行内缩进」(如对齐赋值语句)。本工具只处理每行开头的连续空白字符,行内空格和行尾空格不会改动。如果转换后出现多余空格,可能是原代码行尾本身有空格(肉眼不易发现),建议先用「显示空格」的编辑器检查原文本。
工具能识别 YAML 或 Python 的缩进规则吗?
不能。本工具是纯文本替换器,不解析任何编程语言语法。它只按「行首连续空白字符」做机械替换,不会判断 YAML 的缩进层级是否合法、Python 的缩进深度是否一致。如果代码缩进本身不统一,转换后依然不统一。这种情况下,建议先用语言对应的格式化工具(如 Python 的 autopep8)标准化缩进,再使用本工具做格式转换。
选择 打开 +新窗口 esc关闭