2

通常检查二进制文件是否存在:

if hash gdate 2>/dev/null; then
    gdate "$@"
else
    date "$@"
fi

从命令行运行时:

vagrant@vagrant-ubuntu-saucy-32:~$ hash gdate 2>/dev/null
vagrant@vagrant-ubuntu-saucy-32:~$ echo $?
1

这意味着如果我运行脚本,将调用 date,因为我的系统上没有 gdate。

那么,这意味着上面的代码片段是这样的吗?

if 1; then
  gdate "$@"
else
  date "$@"
fi

我认为 1 在 bash 中评估为 true,所以,不应该选择 if 分支,而不是 else?有人可以为我分解这个片段吗?

4

3 回答 3

3

在 Unix 系统中,退出状态 0 是成功;其他任何事情都是失败的。

test这与内部操作无关。当条件为真时,该test命令也返回(退出状态为)0,当条件为假时返回 1。


评论和答案

pfnuesel问:

这总是正确的吗?在某些特定情况下是否没有类似 C 的真/假评估?

指定一个反例......是的,我相信它总是正确的。运行[ "$var" != "value" ]; echo $?[[ $var != value ]]; echo $?类似的命令组合,看看你得到了什么。

i=0; (( i++ )); echo $?

嗯……有趣;这绝对让我停下来思考。它使事情复杂化,但是(假设您同意它从 1 产生echo $?),我认为这意味着该((命令正在小心地反转逻辑。如果您((针对 的各种值对命令运行测试$i,您会发现当表达式的计算结果为 0 时(就像在您的示例中那样,因为它是一个后增量),然后退出状态为 1,即为 false,但否则,退出状态为 0,这是真的。这适用于bashand ksh(我认为是bash以下ksh)。

我使用这个脚本来帮助自己澄清事情:

for start in {-3..3}
do
    for shell in bash ksh sh
    do
        output=$($shell -c "i=$start;"' if (( i++ )); then echo $? true $i; else echo $? false $i; fi')
        printf "%-4s %4s %s %-5s %s\n" $shell "[$start]" $output
    done
done

输出:

bash [-3] 0 true  -2
ksh  [-3] 0 true  -2
sh   [-3] 0 true  -2
bash [-2] 0 true  -1
ksh  [-2] 0 true  -1
sh   [-2] 0 true  -1
bash [-1] 0 true  0
ksh  [-1] 0 true  0
sh   [-1] 0 true  0
bash  [0] 1 false 1
ksh   [0] 1 false 1
sh    [0] 1 false 1
bash  [1] 0 true  2
ksh   [1] 0 true  2
sh    [1] 0 true  2
bash  [2] 0 true  3
ksh   [2] 0 true  3
sh    [2] 0 true  3
bash  [3] 0 true  4
ksh   [3] 0 true  4
sh    [3] 0 true  4

有趣的是,POSIX shell((语法识别出作为命令的可能性:

如果一个以“”开头的字符序列((如果前面有一个''会被shell解析为算术扩展,那么$实现扩展的shell((expression))可以将“”作为算术表达式来((计算。而不是分组命令。符合要求的应用程序应确保(用空格分隔两个前导 ' ' 字符,以防止 shell 执行算术评估。

于 2013-11-02T22:26:49.413 回答
2

该代码可以按照您的分析工作。唯一的问题是您的最后陈述。在 bash 中,真(“成功”)是零退出状态,非真(“失败”)是非零。见http://tldp.org/LDP/abs/html/exit-status.html

因此,在 bash 中,如果一个命令以零退出,条件语句会将其视为“真”分支。如果命令以非零值退出,则条件将其视为“假”分支。

于 2013-11-02T22:26:37.767 回答
1

该片段尝试1作为命令执行。由于您很可能没有该名称的命令,因此条件为假。if 0 ; then ...会做同样的事情(除非你碰巧有名为0or的命令1)。

如果您想要一个始终为真的条件,有几个选项,其中最简单的是:

if : ; then
     ...
fi

或者,如果您愿意:

if true ; then
    ...
fi
于 2013-11-02T22:27:27.850 回答