如果命令执行失败,为什么if语句的退出代码不是一个失败呢?

3
我很久以为我了解shell,但是却遭遇了意料之外的行为。
考虑以下代码:
#!/bin/bash
foo()
{
    if false
    then
        echo success
    else
        return
    fi
}

foo || echo failure

乍一看,else return 部分似乎是多余的,但实际上它是必要的。代码输出 failure,但如果删除了引用部分,则什么都不会输出。
Bash 手册解释了 if 的行为:

退出状态是最后一个执行的命令的退出状态,如果没有条件测试为真,则为零。

某种程度上,我期望当命令执行失败时,if 会失败。 想象一下,当 echo success 站在那里时,有些依赖命令只有在主命令 (false 在此) 成功执行时才有意义。
这种意外行为背后的逻辑是什么?
针对 bash-4.4 版本。 相关问题:https://dev59.com/L18d5IYBdhLWcg3wkS7Y#63884458

很抱歉有很多错别字! - U. Windl
1
这里的情况是,如果没有条件测试为真,则返回零。 - Shawn
2个回答

2
if语句与return语句不会完全执行;函数将立即返回,返回的退出状态由return提供。该退出状态是在return之前退出的最后一条命令的状态,即false
如果没有returnif语句会完全执行。根据文档,if命令的退出状态定义为:如果在if子句或任何elif子句中的条件都未评估为真,则退出状态为0。这是有道理的,因为if语句成功确定不需要执行任何ifelif块。

我知道,但是如果if返回正在执行的最后一个命令的退出代码(而不是if本身)会不会更有意义呢? - U. Windl
如果最后一个命令在某个从句的主体中,那么它确实会执行。if true; then false; fi 的退出状态为1。如果没有任何条件为真,则整个if语句等同于一个空语句,其定义的退出状态也为0(例如,仅使用$())。 - chepner
如果 cmd 成立,那么 if cmd; then ... fi永远不会是一个空语句,因为无论如何都会执行 cmd!如果 cmd 失败并且没有 else 部分,则最后执行的命令是 cmd。我认为 if cmd; then foo;fi 等同于 cmd && foo。然而,如果 cmd 失败,后者就会失败。 - U. Windl

1

bash手册解释了return的用法:

return

return [n]

Cause a shell function to stop executing and return the value n to its caller. If n is not supplied, the return value is the exit status of the last command executed in the function.

所以:
if false
then
    echo success
else
    # The LAST command is `false` with exit status 1 !
    return  # Returns 1 - returns failure!
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接