通常检查二进制文件是否存在:
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分支而不是其他吗?有人可以为我分解这个片段吗?
答案 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,这是真的。这适用于bash
和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解析为算术扩展(如果前面有'$
'),则实现扩展名为((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 ...
会做同样的事情(除非您碰巧有名为0
或1
的命令。)
如果您希望条件始终为真,则有几个选项,最简单的选项是:
if : ; then
...
fi
或者,如果您愿意:
if true ; then
...
fi