3

我刚开始学习 bash 并且正在阅读有关变量的$?信息。据我了解,$?分配给执行的最后一个命令的退出状态。

例如

$ false; echo $?

将产生 1,并且

$ false; :; echo $?

将产生 0

当我将这些与 if/for 块结合使用时,事情会变得更加复杂。手册页内容如下:

for 名称[in 单词... ]; do 命令; done

为列表中的每个成员执行命令。

循环为项目列表中的for每个成员执行一系列命令。如果in WORDS ...;不存在,则in "$@"假定。对于WORDS中的每个元素,将NAME设置为该元素,并执行命令

退出状态:

返回最后执行的命令的状态。

这意味着:

$ false; for i in 1 2 3; do false; done; echo $?

将产生 1,因为执行的最后一个命令为假。但

$ false; for i in; do false; done; echo $?

或者

$ false; if false; then :; fi; echo $?

尽管 false 是最后执行的命令,但将产生 0。

我的猜测是$?进入 for/if 块时变量设置为 0。我错过了什么吗?

4

3 回答 3

4

根据bash的手册

if 清单then 清单;[elif 列表; then 清单;] ... [else 列表;]fi

iflist执行。如果其退出状态为零,thenlist 则执行。否则,eliflist依次执行每个,如果其退出状态为零,thenlist 则执行相应的命令并完成命令。否则,elselist如果存在,则执行。 (整个块的)退出 状态是执行的最后一个命令(在,块中)的退出状态,如果没有条件测试为真,则为零。if ... fi thenelifelse

于 2017-06-16T12:16:05.513 回答
3

是的,在或语句之后if ..;,退出状态重置为 0。for ..;while ..;

需要明确的是,这并不意味着在退出状态之后fi;done;因为退出状态是最后一个命令退出状态。

编辑:if/elif和/ 之间的命令then不会影响复合语句的退出状态,而then/elseelif/之间执行的最新命令fi设置复合语句的退出状态。

在函数调用之后;退出状态将是return最后一个命令的返回值或退出状态。

带有选项set -e, set -o errexit; shell 在退出状态为 <>0 的命令之后退出,除非后面跟着||或在if ..;语句中。

必须在命令退出后检查退出状态,可以使用逻辑运算符&&||

# to fail fast the process can't continue
simple_command || {
    echo "failed .."
    exit 1
}

错误处理类似于异常,要问的问题是命令失败后进程如何继续?

在管道命令中,退出状态是最后一个命令的退出状态,除了set -o pipefail:退出状态将是管道中最新命令的退出状态,退出状态 <>0。

于 2017-06-16T11:00:34.663 回答
1

命令$ false; for i in; do false; done; echo $?给出 的退出状态for loop。由于它没有错误地退出 for 循环,$?因此为 0。这是一个类似的问题,可能会有所帮助。 如何在bash中获取退出状态循环

于 2017-06-16T10:43:54.910 回答