Bash Shell参数不存在时报错

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)
❺ 恢复正常行为

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!