SuperAPI AI 工具集

shfmt-formatting

编程与开发

查看项目

更新于 10-16 05:09

技能介绍

用途

shfmt 用于格式化 shell 脚本,提升可读性和一致性。它解析脚本为抽象语法树(AST),再以规范格式打印,从而消除风格争论,确保代码库统一。

支持的 Shell 方言

shfmt 支持多种 shell 方言,语法规则各异:

  • POSIX Shell:最可移植,适用于任何 Unix 系统的 /bin/sh。不支持数组、[[ ]] 测试,$() 必须在所有上下文中可用。
  • Bash:脚本中最常用,支持扩展特性,如数组、[[ ]]、算术运算等。
  • mksh (MirBSD Korn Shell):Korn shell 变体,有自己的扩展,如关联数组。
  • Bats (Bash Automated Testing System):用于 Bats 测试文件。

主要能力

格式化模式

  • 缩进:统一脚本中的缩进,可通过 -i 指定空格数(如 -i 2 为两空格,-i 0 为制表符)。
  • 空格:规范化操作符和关键字周围的空格。
  • 分号与换行:将多个语句拆分为独立行,移除行尾多余分号。
  • Here Documents:保留 here-doc 内容,但规范化缩进;<<- 允许剥离制表符。
  • 函数定义:统一函数格式,-fn 选项可将大括号置于新行。
  • Case 语句:统一 case 格式,-ci 选项可缩进 case 分支。
  • 二元操作符:默认将 && 等置于行尾,-bn 选项置于行首。
  • 重定向:默认无空格,-sr 选项在重定向符号后添加空格。

常见格式化问题

  • 混合制表符与空格:使用 shfmt -i 2 -w 统一为空格,或 -i 0 统一为制表符。
  • 行尾分号:shfmt 自动移除。
  • 引号不一致:shfmt 保留引号风格,但规范化不必要的引号。
  • 长行:shfmt 不自动换行,需手动使用续行符。
  • 数组格式:按书写方式保留单行或多行格式。

编辑器集成

  • VS Code:安装 "shell-format" 扩展,配置 shellformat.path 和 flag。
  • Vim/Neovim:使用 ALE 或原生格式化,设置 formatprg。
  • Emacs:使用 reformatter 包定义 shfmt 命令。
  • JetBrains IDE:安装 "Shell Script" 插件,在设置中配置 shfmt 路径和选项。

检查与 Diff 模式

  • 检查格式(CI 模式):shfmt -d 显示差异(需更改时退出码 1),shfmt -l 列出需格式化的文件。
  • 原地格式化:shfmt -w 覆盖文件。
  • 预览更改:shfmt 输出到 stdout,或重定向到文件。

Git 集成

  • 格式化暂存文件:通过 git diff --cached 获取暂存 .sh 文件并运行 shfmt -w。
  • Pre-commit 钩子:检查暂存文件格式,若需格式化则阻止提交。
  • 格式化变更文件:格式化自 main 分支以来更改的文件。

压缩(高级)

shfmt -mn 可移除空白和注释,压缩脚本,仅用于分发,不用于开发。

使用方式

基本命令:

  • 格式化并输出到 stdout:shfmt script.sh
  • 原地格式化:shfmt -w script.sh
  • 检查差异:shfmt -d script.sh
  • 列出需格式化文件:shfmt -l .
  • 指定缩进:shfmt -i 2 -w script.sh
  • 强制方言:shfmt -ln bash script.sh

适用场景

  • 统一 shell 脚本格式,确保团队一致性。
  • 集成到开发工作流,如保存时自动格式化。
  • 在 CI/CD 中验证格式。
  • 解决脚本中的格式问题。
  • 配置编辑器保存时格式化。

限制

  • shfmt 不自动换行长行,需手动续行。
  • 不支持 # shfmt:ignore 注释,需通过文件排除来保留特定格式。
  • 压缩模式移除注释和空白,仅适用于分发。
  • 需确保 shell 方言与脚本 shebang 匹配,否则可能解析错误。
  • 格式化后应审查更改,确保符合预期。

最佳实践

  • 保存时格式化:配置编辑器自动格式化。
  • CI 验证:在流水线中运行 shfmt -d。
  • 团队统一设置:提交 .shfmt.toml 到仓库。
  • 匹配 Shebang:确保方言与脚本 shebang 一致。
  • 格式化后审查:验证更改合理。
  • 不混用风格:所有脚本使用相同设置。
  • 使用 Pre-commit 钩子:防止未格式化代码提交。

故障排除

  • 解析错误:先用 bash -n 或 sh -n 检查语法。
  • 方言检测错误:使用 -ln 强制指定方言。
  • 保留有意格式:将代码移至不被 shfmt 处理的文件,或接受格式化版本。