
Shell 脚本中正确解析和校验参数,是保证脚本健壮性和易用性的关键。不加检查地直接使用 $1、$2 等位置参数,容易导致逻辑错误、命令执行失败,甚至安全风险。
使用 getopts 进行标准 POSIX 参数解析
getopts 是 Shell 内置命令,支持短选项(如 -f、-n 3)和带参数的选项,语法简洁且可移植性强。它自动处理选项拼接(如 -abf file)、缺失参数报错,并通过 OPTARG 提供参数值。
常见写法示例:
#!/bin/bash
while getopts "hn:f:" opt; do
case $opt in
h) echo "Usage: $0 [-h] [-n NUM] [-f FILE]"; exit 0 ;;
n) num=$OPTARG ;;
 >f) file=$OPTARG ;;
 :\) echo "Option -$OPTARG requires an argument." >&2; exit 1 ;;
 :\?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
esac
done
shift $((OPTIND-1)) # 跳过已处理的选项,剩余为非选项参数
- 选项字符串
"hn:f:"中,h和n后无冒号表示不带参数;f:表示-f必须跟一个值 -
:\)捕获“缺少参数”情况(如-f后无文件名),:\?捕获非法选项(如-x) -
shift $((OPTIND-1))是关键操作,否则$1仍指向第一个选项而非首个非选项参数
对必需参数做存在性与合法性校验
即使参数被成功解析,也需验证其内容是否符合预期:是否存在、是否为空、是否满足格式或权限要求。
- 检查变量是否为空:
[ -z "$file" ] && { echo "Error: -f is required." >&2; exit 1; } - 检查文件是否存在且可读:
[ ! -r "$file" ] && { echo "Error: cannot read '$file'." >&2; exit 1; } - 校验数字参数范围:
[[ "$num" =~ ^[0-9]+$ ]] || { echo "Error: -n must be a positive integer."; exit 1; } - 避免路径遍历:
[[ "$file" == /* ]] || { echo "Error: absolute path required for safety."; exit 1; }
统一错误输出与退出状态管理
错误信息应输出到 stderr(>&2),并返回非零退出码(通常用 1,也可按需定义:2=参数错误,3=IO 失败等)。避免混用 echo 和 printf 输出错误,保持风格一致。
- 封装错误函数提升可读性:
die() { printf "%s\n" "$*" >&2; exit 1; },调用die "Missing -f" - 在脚本开头设置
set -e可让命令失败时立即退出,但需谨慎——它不捕获管道、条件判断内的失败,建议搭配set -u(未定义变量报错)和set -o pipefail使用 - 用
trap 'cleanup' EXIT注册退出清理逻辑(如临时文件删除),确保异常退出时也能释放资源
支持长选项需借助外部工具或手动解析
Bash 原生 getopts 不支持 --help 这类长选项。若需兼容 GNU 风格,可:
- 用
getopt(注意:非内置,是 util-linux 工具,行为在不同系统略有差异,需加-o和--long参数) - 手动解析:
for arg in "$@"; do case $arg in --help) show_help; exit 0;; --file=*) file=${arg#--file=};;,但需注意空格分隔和引号处理 - 优先推荐短选项 + 清晰帮助文本,兼顾简洁与兼容性;长选项更适合复杂工具,此时建议迁移到 Python/Go 等语言









