2016-03-01 27 views
0

首先我不是Bash专业版。我几个月前发现,如果我使用带花括号的短路操作符&&||,那么如果第一条语句以真值存在,如果真块中的最后一条语句退出非零,那么失败块也将被执行。就像这样:了解Bash短路

returnNumber 0 && { 
    echo 'OK' 
    returnNumber 1 
} || { 
    echo 'NG' 
} 

将输出:

OK 
NG 

于是,我找了这个最简单的解决方案,以及与此想出了:

returnNumber 0 && { 
    echo 'OK' 
    returnNumber 1 
    : 
} || { 
    echo 'NG' 
} 

我知道,这是很容易忽略内置结肠,但它是一种解决方法的正确方法?

+0

不要运动了使用特殊的语法。当你只写'if-then-else-fi'时,大多数人都会理解。 尝试考虑有效的例外情况。我仍然不确定我的答案http://stackoverflow.com/a/28478184/3220113:它是有效的,但很难阅读。 –

回答

5

这实际上是一个很常见的Bash pitfall。它是不是的一个bug。

returnNumber 0的计算结果为真,所以第二个块(由逻辑和&&加入)也进行评估以确保first && second的结果仍然为真。
第二个块输出OK但计算结果为false,所以现在first && second的结果为false。这意味着第三部分(由逻辑或||加入)也必须进行评估,导致也会显示NG


而不是依靠&&||,你应该使用if声明:

if returnNumber 0; then 
    echo 'OK' 
    returnNumber 1 
else 
    echo 'NG' 
fi 

TL;博士:切勿使用x && y || zy可以返回一个非零退出状态。

0

Llama先生已经正确地回答了这个问题,这只是为了快速参考不同的“组合”会发生什么。 cmd0是具有零退出状态的“命令”,且cmd1的值不为零。

cmd0() { echo -n "[[email protected]]"; return 0; } 
cmd1() { echo -n "[[email protected]]"; return 1; } 
second() { echo "[second]"; } 

doit() { echo "case: [email protected]"; eval "[email protected]"; echo; } 

doit 'cmd0 start && cmd0 first && second' 
doit 'cmd0 start && cmd0 first || second' 
doit 'cmd0 start || cmd0 first && second' 
doit 'cmd0 start || cmd0 first || second' 

doit 'cmd0 start && cmd1 first && second' 
doit 'cmd0 start && cmd1 first || second' 
doit 'cmd0 start || cmd1 first && second' 
doit 'cmd0 start || cmd1 first || second' 

doit 'cmd1 start && cmd0 first && second' 
doit 'cmd1 start && cmd0 first || second' 
doit 'cmd1 start || cmd0 first && second' 
doit 'cmd1 start || cmd0 first || second' 

doit 'cmd1 start && cmd1 first && second' 
doit 'cmd1 start && cmd1 first || second' 
doit 'cmd1 start || cmd1 first && second' 
doit 'cmd1 start || cmd1 first || second' 

生产:

case: cmd0 start && cmd0 first && second 
[start-0][first-0][second] 

case: cmd0 start && cmd0 first || second 
[start-0][first-0] 

case: cmd0 start || cmd0 first && second 
[start-0][second] 

case: cmd0 start || cmd0 first || second 
[start-0] 

case: cmd0 start && cmd1 first && second 
[start-0][first-1] 

case: cmd0 start && cmd1 first || second 
[start-0][first-1][second] 

case: cmd0 start || cmd1 first && second 
[start-0][second] 

case: cmd0 start || cmd1 first || second 
[start-0] 

case: cmd1 start && cmd0 first && second 
[start-1] 

case: cmd1 start && cmd0 first || second 
[start-1][second] 

case: cmd1 start || cmd0 first && second 
[start-1][first-0][second] 

case: cmd1 start || cmd0 first || second 
[start-1][first-0] 

case: cmd1 start && cmd1 first && second 
[start-1] 

case: cmd1 start && cmd1 first || second 
[start-1][second] 

case: cmd1 start || cmd1 first && second 
[start-1][first-1] 

case: cmd1 start || cmd1 first || second 
[start-1][first-1][second]