首页/系统/Linux 运维命令速查/expand / unexpand 制表符与空格互转
文本处理77 条

expand / unexpand 制表符与空格互转

expand 把 Tab 换成空格(对齐跨编辑器更稳),unexpand 反过来把空格压缩为 Tab,-a 处理行中所有空白。

Linux 运维命令速查系统更新于 2026-10-13

expand 是什么

expand 把制表符换成等量空格,unexpand 反过来把空格压回制表符,两者都属于 GNU coreutils。它们要解决的是「同一份文件在不同编辑器、不同工具里对齐效果不一致」的问题:Tab 的显示宽度随编辑器设置变化,空格则处处一样。unexpand 默认只处理行首空白,加 -a 才会连行内空白一起转换。

基本信息

所属GNU coreutils(各发行版默认安装)
语法expand [-t 宽度] [文件] / unexpand [-a] [-t 宽度] [文件]
默认制表位8 列,可用 -t 改为其他宽度
观察工具cat -A 里 ^I 表示 Tab,行尾 $ 表示换行

典型使用场景

  • 代码或配置多人协作时统一缩进,避免 Tab 宽度不同造成的错位
  • 提交前把同事留下的 Tab 缩进统一成空格,减少无意义的 diff 噪音
  • 把大段空格缩进压成 Tab,缩小老格式文件体积
  • 排查缩进敏感文件(Python、YAML)里混用 Tab 与空格的问题
  • 处理老系统导出的、靠 tab 对齐的固定宽度报表
  • 对比两份文件差异前先做一次空白统一

常用示例

常用示例
expand -t 4 tabbed.txt > spaced.txt      # Tab 换成 4 个空格
expand -t 2 config.ini > config.fixed    # 统一为 2 空格缩进
unexpand -a spaced.txt > tabbed.txt      # 行内连续空格也转成 Tab
unexpand --first-only spaced.txt         # 只转行首空白(默认行为)
expand -t 8 file.txt | head -5           # 先看前几行效果再整体处理
cat -A file.txt | head                   # 看清是 Tab 还是空格
grep -P '\t' -l ./*.py                   # 找出含 Tab 的 Python 文件
diff <(cat -A a.txt) <(cat -A b.txt)     # 对比空白差异的真实形态

常用选项

选项作用说明
-t N设置制表位宽度expand 默认 8,可给逗号分隔的多个位置
-i只转换行首空白(expand)行内 Tab 保持原样
-a转换所有空白(unexpand)不加则只处理行首
--first-only只转换行首(unexpand)与默认行为一致,写出来更明确
多个文件依次处理并合并输出等价于先 cat 再转换
Makefile 的规则行必须以真实 Tab 开头:expand 或 unexpand -a 会把规则行变成空格,make 直接报 missing separator。处理 Makefile 前先确认规则,或用编辑器的缩进转换单独处理。
空格与 Tab 的转换不是无损往返:当空格数不落在制表位上时无法精确还原原始形态,来回转换会让文件内容持续变化。重要文件先提交或备份再动手。
Python 3 不允许同一文件混用 Tab 与空格缩进,YAML 同样如此。批量统一缩进后仍要跑一次语法检查或解析测试,别只看文件能不能打开。

易错点

  • 对 Makefile 执行 expand 或 unexpand -a:规则行变成空格,make 报 missing separator,只能手工改回
  • 以为转换可以逆:空格数不在制表位上时无法还原,来回转换会丢失原始形态
  • unexpand 不加 -a 却期待行内空格变 Tab:默认只处理行首,行内空白保持原样
  • 批量转换前既不备份也不提交:对齐关系被改写且无法对比,出问题回不去
  • 统一缩进后不做语法检查:混用问题看似解决,解析时才暴露更晚

数据来源与参考

  • man 1 expand(GNU coreutils 手册)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌