使用 vscode 编写 shell 脚本时,函数里语句 local var=$(mycmd)
被提示有问题,查看发现是插件 shellcheck 检查代码后给出的提示 "Declare and assign separately to avoid masking return values. shellcheck(SC2155)"。
我该如何理解这个提示呢,为什么需要分开声明和赋值?
在 Shell 脚本中,命令的返回值(exit status)是一个非常重要的概念。返回值通常用于判断命令是否成功执行。返回值为 0 表示成功,非 0 表示失败。
shellcheck 的 wiki 解释是 命令的退出状态被 local 变量创建的退出状态所覆盖。 具体意思是 当一个命令执行后紧接着创建一个局部变量(例如使用 local 关键字在函数内定义变量),脚本会将最后执行的操作(即局部变量创建)的退出状态作为整个操作序列的退出状态。因此,即使前面的命令失败了(返回非零退出状态),如果局部变量的成功创建(通常总是成功的,除非存在如重复定义等错误)返回了一个成功的退出状态(通常是 0),那么这个成功的状态就会覆盖前面命令的实际退出状态。
这种写法可能会掩盖命令执行中的错误,导致逻辑判断、set -e
、traps 工作出现问题,因为后续依赖于正确退出状态的代码可能不会按照预期的方式工作。为了避免这种情况,应该确保命令的退出状态不会被后续无关的操作所覆盖,或者显式地检查和保存重要的退出状态。
演示代码如下:
$ f() { local foo=$(false) && echo "error was hidden"; }; f
error was hidden
$ f() { local foo; foo=$(false) && echo "error was hidden"; }; f
$
为了提高代码的可读性和健壮性,建议将声明和赋值分开写,尤其是在涉及命令执行时。这样可以确保命令的返回值不会被掩盖。
示例代码
my_function() {
local var
var=$(mycmd)
if [ $? -ne 0 ]; then
echo "Command failed"
return 1
fi
echo "Variable assigned: $var"
}
my_function
echo "Function returned: $?"
在这个例子中,var
先被声明为局部变量,然后执行 mycmd
并捕获输出。紧接着检查命令的返回值,确保错误能够被正确处理。
•https://www.shellcheck.net/wiki/SC2155