Bash Shell参数不存在时报错,这些能够设置默认值的便捷写法都挺酷,但有时你需要强制用户指定某个值,否则就无法继续往下进行。用户有可能会遗漏某个参数,因为他们确实不知道该怎样调用脚本。你希望能给用户点提示,省得他们自己瞎猜。相较于堆砌成堆的 if 语句,有没有更简洁的方法来检查各个参数?
解决方案
引用参数时使用 ${:?}
语法,如下例所示。如果指定参数不存在或为空,那么 bash 会输出错误消息并退出。
#!/usr/bin/env bash
# 实例文件:check_unset_parms
#
USAGE="usage: myscript scratchdir sourcefile conversion"
FILEDIR=${1:?"Error. You must supply a scratch directory."}
FILESRC=${2:?"Error. You must supply a source file."}
CVTTYPE=${3:?"Error. ${USAGE}"}
如果执行脚本时没有指定足够的参数,则会出现下列结果。
$ ./myscript /tmp /dev/null
./myscript: line 7: 3: Error. usage: myscript scratchdir sourcefile conversion
$
讨论
bash 会测试各个参数,如果参数不存在或为空,则输出错误信息并退出。
$3
所对应的错误消息中使用了另一个 shell 变量。你甚至可以在其中执行其他命令。
CVTTYPE=${3:?"Error. $USAGE. $(rm $SCRATCHFILE)"}
如果 $3
不存在,则错误消息中会包含短语 "Error."
、变量$USAGE
的值以及 rm $SCRATCHFILE
命令的输出。我们先说到这里。你可以让自己的 shell 脚本紧凑得吓人,没错,我们说的就是吓人(awfully)。最好还是多加些空白字符,让代码逻辑更加清晰可读。
if [ -z "$3" ]
then
echo "Error. $USAGE"
rm $SCRATCHFILE
fi
另一方面的考虑:${:?}
生成的错误信息包含 shell 脚本文件名和行号。例如,以下是示例产生的运行结果片段。
$ ./check_unset_parms
./check_unset_parms: line 5: 1: Error. You must supply a scratch directory.
$ ./check_unset_parms somedir
/tmp/check_unset_parms: line 6: 2: Error. You must supply a source file.
$ ./check_unset_parms somedir somefile
./check_unset_parms: line 7: 3: Error. usage: myscript scratchdir sourcefile \
conversion
因为无法控制错误消息的这部分内容,而且这看起来好像是 shell 脚本自身出现的错误,再加上可读性的问题,该技术在商业级的 shell 脚本中并不多见。(不过确实有助于调试。)
要想所有变量都具备这种行为,同时又不想逐个改动,可以使用 set -u 命令,“在变量替换时,将不存在的变量视为一种错误”。
$ echo "$foo" ➊
$ set -u ➋
$ echo "$foo"
bash: foo: unbound variable ➌
$ echo $? # 退出码
1
$ set +u ➍
$ echo "$foo" ➎
$ echo $? # 退出码
0
$
❶ 一开始是正常行为
❷ 启用 nounset(-u)
❸ 现在看到了错误信息和故障退出码
❹ 再次关闭 nounset(-u)
❺ 恢复正常行为
酷客网相关文章:
评论前必须登录!
注册