这个bash片段是如何工作的?

时间:2013-11-02 22:22:52

标签: linux bash

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

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分支而不是其他吗?有人可以为我分解这个片段吗?

3 个答案:

答案 0 :(得分:3)

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

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


评论和解答

pfnuesel问道:

  

这总是如此吗?在某些特定情况下,是不是存在类似C的真/假评价?

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

  

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

嗯...有趣;这绝对让我停下来思考。它使事情变得复杂,但(假设你同意它从echo $?产生1),我认为这意味着((命令正在小心地反转逻辑。如果在((命令上对$i的各种值运行测试,您会发现当表达式求值为0时(就像在示例中那样,因为它是后增量),那么退出状态为1,这是假,但否则,退出状态为0,这是真的。这适用于bashksh(我认为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解析为算术扩展(如果前面有'$'),则实现扩展名为((expression))的shell “被评估为算术表达式可以将”((“视为算术评估而不是分组命令。符合要求的应用程序应确保将两个前导“(”字符与空格分开,以防止shell执行算术评估。

答案 1 :(得分:2)

代码按照您的分析工作。唯一的问题是你的最后陈述。在bash中,true(“success”)是零退出状态,non-true(“failure”)是非零。见http://tldp.org/LDP/abs/html/exit-status.html

因此,在bash中,如果命令以零退出,则条件将看作“真”分支。如果命令以零以外的任何值退出,则条件将把它视为“假”分支。

答案 2 :(得分:1)

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

如果您希望条件始终为真,则有几个选项,最简单的选项是:

if : ; then
     ...
fi

或者,如果您愿意:

if true ; then
    ...
fi