Bash 严格模式定义如下:
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
http://redsymbol.net/articles/unofficial-bash-strict-mode/
考虑以下 Bash 脚本中位置参数的解析:
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
usage() {
echo ""
echo "usage:"
echo "$0 [options]"
echo " -r | --redirect-uri: redirect uri"
echo " -a | --app-role: app role id"
echo " -h | --help: help"
echo ""
}
redirect_uri=""
app_role=""
while [ "$1" != "" ]; do
case $1 in
-r | --redirect-uri)
shift
redirect_uri="$1"
;;
-a | --app-role)
shift
app_role="$1"
;;
-h | --help)
usage
exit 0
;;
*)
usage
exit 1
;;
esac
shift
done
...
这不适用于以下错误,例如:
$ ./app.sh -r https://example.net:8080/auth/callback -a 53b37b21-2c6e-4731-a5e5-15b98052c686
./app.sh: line 18: $1: unbound variable
我认为原因是while
条件中的最终检查, after shift
, where$1
未定义。
使用 Bash 严格模式时,如何终止while
语句中的参数解析而不导致脚本崩溃?
答案1
您会收到unbound variable
错误,因为您试图$1
在未定义的情况下访问它,而在while
循环的最后一次迭代之后它不会出现。因此,有问题的命令是您使用的测试while
:
[ "$1" != "" ]
相反,使用类似的东西
[ "${1+set}" = set ]
或者
[ -n "${1+set}" ]
参数扩展${parameter+word}
将扩展为word
ifparameter
是一个现有变量(无论它是否具有非空值)。这个词set
是任意选择的,但在某种程度上暗示了它的用途。
您还可以测试$#
,它保存位置参数的数量:
[ "$#" -ne 0 ]
或者
[ "$#" -gt 0 ]
只要存在仍需要处理并从列表中移出的位置参数,这些算术测试都是正确的。
nounset
这些变体中的任何一个都避免了与shell 选项 ( )施加的限制相冲突set -u
。