用途
shfmt 是一个 shell 解析器、格式化器和解释器,支持 POSIX Shell、Bash 和 mksh。该技能用于配置 shfmt,使 shell 脚本在不同项目和团队中获得一致的格式化结果,包括配置文件设置、EditorConfig 集成和团队标准化。
主要能力
shfmt 的配置方式按优先级从高到低为:命令行参数(最高)、EditorConfig 设置、.shfmt.toml 或 shfmt.toml 文件。
使用方式
TOML 配置文件
在项目根目录创建 .shfmt.toml 或 shfmt.toml,基础配置示例:
# Shell dialect (posix, bash, mksh, bats)
shell = "bash"
# Indent with spaces (0 for tabs)
indent = 2
# Binary operators at start of line
binary-next-line = true
# Switch cases indented
switch-case-indent = true
# Redirect operators followed by space
space-redirects = false
# Keep column alignment paddings
keep-padding = false
# Function opening brace on next line
func-next-line = false
配置项说明
- shell:指定解析用的 shell 方言,可取 posix、bash、mksh、bats。未指定时根据 shebang 自动检测(#!/bin/sh 对应 posix;#!/bin/bash 或 #!/usr/bin/env bash 对应 bash;#!/bin/mksh 对应 mksh)。
- indent:控制缩进风格,2 表示 2 个空格,4 表示 4 个空格,0 表示使用 Tab。
- binary-next-line:控制二元运算符位置。false 时运算符在行尾,true 时运算符在下一行行首。
- switch-case-indent:控制 case 语句缩进。false 时 case 与 switch 同级,true 时 case 缩进在 switch 内。
- space-redirects:控制重定向周围空格。false 时重定向符号前无空格(如
echo "hello" >file.txt),true 时前有空格(如echo "hello" > file.txt)。 - keep-padding:是否保留对齐填充。false 时移除多余对齐空格,true 时保留。
- func-next-line:控制函数花括号位置。false 时左花括号在同一行,true 时在下一行。
EditorConfig 集成
shfmt 支持 EditorConfig。可在 .editorconfig 中配置:
[*.sh]
indent_style = space
indent_size = 2
# shfmt-specific options
shell_variant = bash
binary_next_line = true
switch_case_indent = true
space_redirects = false
keep_padding = false
function_next_line = false
EditorConfig 键与 shfmt 参数映射:
| shfmt 参数 | EditorConfig 键 |
|---|---|
| -i | indent_size(0 表示 Tab) |
| -ln | shell_variant |
| -bn | binary_next_line |
| -ci | switch_case_indent |
| -sr | space_redirects |
| -kp | keep_padding |
| -fn | function_next_line |
命令行参数
# 就地格式化文件
shfmt -w script.sh
# 显示改动差异
shfmt -d script.sh
# 列出需要格式化的文件
shfmt -l .
# 格式化并输出到 stdout
shfmt script.sh
常用格式化参数:-i 4(4 空格缩进)、-i 0(Tab 缩进)、-ln bash(指定 bash 方言)、-bn(二元运算符换行)、-ci(case 缩进)、-sr(重定向前加空格)、-kp(保留填充)、-fn(函数花括号换行)。组合示例:
shfmt -i 2 -ci -bn -w script.sh
项目配置示例
最小 Bash 项目:
shell = "bash"
indent = 2
POSIX 兼容脚本:
shell = "posix"
indent = 4
binary-next-line = false
switch-case-indent = false
现代 Bash 全特性:
shell = "bash"
indent = 2
binary-next-line = true
switch-case-indent = true
space-redirects = false
func-next-line = false
团队标准化:
shell = "bash"
indent = 2
binary-next-line = true
switch-case-indent = true
keep-padding = false
CI/CD 集成
GitHub Actions:
name: Shell Format Check
user-invocable: false
on: [push, pull_request]
jobs:
shfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install shfmt
run: |
curl -sS https://webinstall.dev/shfmt | bash
export PATH="$HOME/.local/bin:$PATH"
- name: Check formatting
run: shfmt -d .
Pre-commit Hook:
repos:
- repo: https://github.com/scop/pre-commit-shfmt
rev: v3.8.0-1
hooks:
- id: shfmt
args: ["-w"]
Makefile Target:
.PHONY: fmt-check fmt
fmt-check:
shfmt -d .
fmt:
shfmt -w .
适用场景
- 在新项目中设置 shfmt
- 配置全团队范围的格式化标准
- 将 shfmt 集成到 CI/CD 流水线
- 排查配置问题
- 在不同配置方式之间迁移
- 为 shell 脚本设置 EditorConfig
最佳实践
- 提交配置文件:始终提交 .shfmt.toml 以保证团队一致性。
- 匹配方言:让 shell 设置与脚本 shebang 一致。
- 优先使用 EditorConfig:便于 IDE 集成。
- CI 强制检查:在 CI 中运行 shfmt -d 以发现格式问题。
- 保持缩进一致:选定 2 或 4 个空格并坚持使用。
- 记录选择:为非默认选项添加注释说明。
- 锁定版本:在 CI 中固定 shfmt 版本以保证可复现性。
限制与排错
配置文件未生效时,按优先级顺序检查:命令行参数覆盖一切;文件所在目录的 EditorConfig;项目根目录的 .shfmt.toml。
shell 方言错误时,确认 shebang 与配置一致,例如使用 shell = "bash" 时脚本应包含 #!/usr/bin/env bash 或 #!/bin/bash。
EditorConfig 未被识别时,确保 EditorConfig 文件位于父目录链中且包含正确分区,例如 [*.sh] 与 shell_variant = bash。