我已经使用 Bash 很长时间了,但似乎还是遗漏了一些东西。请考虑以下代码:
function surprise {
true && {
echo 'Expected';
false;
} || {
echo 'Unexpected';
}
}
surprise;
这是我的实际问题和输出的简短演示:
Expected
Unexpected
到目前为止,我一直认为“Expected”块返回的任何内容都不会影响||
前面的“Unexpected”块,但似乎||
并没有针对命令的输出进行检查true
,而是实际上针对false
括号内的命令进行检查。
有人能解释一下刚才到底发生了什么吗?提前谢谢。
答案1
看起来,|| 不是针对 true 命令的输出进行检查,而是针对括号内的 false 命令进行检查。
可以这么说。
x && y || z
不是if/then/else 结构,也不应该用作 if/then/else 结构。它是布尔运算符的组合(相当于“x AND y OR z”),并将评估尽可能多的命令以确定结果。(除非按括号或大括号分组,否则评估是从左到右的,就像在大多数编程语言中一样,因此顺序是(x && y) || z
。)
因此,为了确定的结果x && y
,当X是真的,是也必须进行评估。另一方面,当X为假,那么结果无论如何都是假的,所以它只会短路并跳过是。
中间的值是否是单个命令或{cmd; cmd; cmd}
块实际上并不重要;在这种情况下,它仅仅帮助您看到实际效果。
答案2
首先:你可以将每个“块”视为复杂的命令,而不是明显不同的东西。因此,你真正拥有的只是:
cmd1 && cmd2 || cmd3
...事实上和cmd2
是cmd3
块而不是简单命令并不重要。现在,重要的是,给定该命令序列,&&
和||
“运算符”的逻辑优先级使其如下所示:
( cmd1 && cmd2 ) || cmd3
(注意:实际上,这些括号会强制使用子 shell。我忽略了这一点。)如果你看一下它的逻辑结构,它是,所以很明显如果失败,( something ) || cmd3
它会运行。但实际上是,如果 *both和都成功,它会成功——这意味着如果cmd3
something
something
cmd1 && cmd2
cmd1
cmd2
任何一个 cmd1
或cmd2
失败。
因此,从逻辑上讲,cmd3
如果任何一个 cmd1
或cmd2
失败。在您的实际代码中,cmd2
总是失败,所以cmd3
总是运行。
答案3
双与(&&
)和双管道(||
)在 Linux 的进程控制中具有含义。
把它们视为逻辑运算符。
command1 && command2
或者
command1 || command2
或者
command1 && command2 || command3
基本上,在这 3 种情况下,command1
都会运行。如果退出状态为非零(某种类型的错误),则认为未成功运行。
通过&&
编程中的逻辑与思考,无需运行第二条命令,因为第一条命令在某种程度上失败了。
考虑||
到逻辑或,如果第一个条件成功(退出 0),则无需检查第二个条件,只有其中一个条件必须成功。
对于第三个示例,如果command1
成功,它将运行command2
。如果不成功,它将运行command3
在您的示例中,正在检测您的命令||
的退出状态。false