我以为我很了解shell,但是我被意想不到的行为咬了。
考虑以下代码:
#!/bin/bash
foo()
{
if false
then
echo success
else
return
fi
}
foo || echo failure
现在,乍一看,人们会认为else return
部分是多余的,但它不是。代码原样输出failure
,但是当被引用的部分被删除时,则nothing输出。
bash手册解释(对于if
):
退出状态为最后执行的命令的退出状态,如果没有条件测试为真,则为零。
当命令失败时,我期望if
失败。想象一下,在echo success
所在的位置,实际上有一些依赖的命令,这些命令只有在主命令(这里是false
)成功时才有意义。
这种意外行为背后的逻辑是什么?
参见bash-4.4。相关:https://stackoverflow.com/a/63884458/6607497
if
语句实际上从未与return
语句完成;函数立即返回,退出状态由return
提供。该退出状态是return
之前退出的最后一个命令的状态,即false
。
如果没有return
,if
不会完成,并且如文档所述,如果if
子句或任何elif
子句中的条件都没有计算为真,则if
命令的退出状态定义为0。这是有道理的,因为if
语句成功地确定了if
或elif
块都不需要执行。
bash手册解释(对于return
):
返回return [n]
导致shell函数停止执行并将值n返回给调用者。如果未提供n,则返回值为退出状态最后执行的命令
:
if false
then
echo success
else
# The LAST command is `false` with exit status 1 !
return # Returns 1 - returns failure!
fi