变量判空设默认值
Shell 脚本中需要给某个变量赋值时,若数据来源不可控(如:用户输入、文件列表、环境变量),通常需要给变量设置一个默认值以方便对数据同一处理。Bash 中有多种语法支持设置这样的默认值:
- 为空返回默认值:
${var:-def}:若var为空返回'def' - 为空设置默认值:
${var:=def}:若var为空将它置为'def'并返回 - 非空返回指定值:
${var:+flag}:若var不为空时返回'flag',用于测试变量是否存在 - 判空断言:
${var:?msg}:若var不为空返回其值,为空时输出var:msg并中断执行,同断言- 省略
msg时输出var: parameter null or not set.
- 省略
命令参数解析
Bash 命令在使用中通常有 3 种传参方式:
- 直接使用位置参数,如
cmd status,其中入参status在函数 cmd 中可使用位置参数$1获取。 - 使用 Bash 内置短格式参数解析工具
getopts,如cmd -v -f filename.txt - 使用非标准 Unix 命令
getopt解析长格式参数,如cmd --version --file filename.txt
特别的,大多数 Linux 的发行版都带了getopt工具,但getopt的旧版本 BUG 不少,这些 BUG 在新的增强版本中被修复(执行getopt -T; echo $?输出4表示该版本为增强版)。比如 MacOS 自带的 getopt 为旧版本,可使用 brew 安装增强版:brew install gnu-getopt 安装后将可执行文件加入 PATH:echo -e '\nexport PATH="/usr/local/opt/gnu-getopt/bin:$PATH"\n' >> ~/.bash_profile
总结
当编写 Bash 脚本读取用户输入的指令时,位置参数不利于功能拓展,长指令参数输入过于繁琐且依赖外部环境不利于代码移植,内置的getopts可作为中庸之道而被视为较优选择;且通常在指令参数解析过程中配合变量判空和设默认值写法,如:
#!/usr/bin/env bash
# 解析短格式参数 -a -f input
while getopts 'af:c:' OPT; do # 参数键存入变量 OPT
case "$OPT" in
a)
echo "a is open" # 获取无值参数
;;
f)
echo "f is $OPTARG" # 获取有值参数,参数值在内置变量 OPTARG 中
;;
?) # 其他配置项,如 -x
echo "usage: $(basename $0) [-a] [-f xxx]" >&2
exit 1 # 退出脚本,并将结果变量 $? 置为1
;;
esac
done
# $OPTIND 在首次执行时是1之后每次解析后累加;通过shift可将短格式参数弹出,保持此后的参数从位置 $1 开始
shift "$(($OPTIND - 1))"