echo 1 && false && echo 2 || echo 3
1
3
echo 2 || echo 3
2
在上面的代码中,为什么在第一种情况下不打印 2 ?为什么在第二种情况下会打印 2 ?
答案1
更一般的问题shell 的控制和重定向运算符是什么?它的答案可能会回答你的问题,但我会给你一些经验法则供你参考。
如果您有一个很长的和/或列表,那么您可能会将每个列表视为
||
“如果此列表中最近执行的部分失败的,运行下一部分”(其中“失败”表示返回非零退出状态)。使用相同类型的推理,您可能会说这
&&
意味着“如果此列表中最近执行的部分成功了,运行下一部分”(其中“成功”意味着返回零退出状态)。
上面描述的是通常所说的短路评估。
以您的代码为例,假设每个代码echo
都有机会执行(echo
将失败如果标准输出流已关闭):
echo 1 && false && echo 2 || echo 3
第一个echo 1
成功,因此false
运行。 false
失败(按设计),所以echo 2
才不是跑步。echo 3
,另一方面,由于列表 ( false
) 的最近执行的部分失败而运行。
看着
echo 2 || echo 3
在这里,echo 2
首先运行,但echo 3
没有运行,因为列表中最近执行的部分没有失败。
答案2
&&
我对||
这个答案有一个简短的解释:https://unix.stackexchange.com/a/31881/4506m但这里有对您的特定示例的更详细解释。
首先,重要的是要知道 unix 命令成功或者失败无论它们可能产生或不产生什么输出。更准确地说,如果命令的退出状态为零,则该命令成功;如果退出状态非零,则命令失败,但从退出状态的角度思考是令人困惑的。
鉴于此,您可能想要考虑
cmd1 && cmd2 && ... && cmdN
从左到右评估命令,直到失败为止,以及cmd1 || cmd2 || ... && cmdN
从左到右评估命令,直到成功为止。
那么,让我们从你的第一个例子
echo 1 && false && echo 2 || echo 3
&&
由于没有括号的组合和运算会变得更加混乱||
,这使得预期的分组不清楚。事实证明,&&
和||
具有相同的优先级并且分组到左侧,但是像这样的混合序列常常令人困惑。这个表达式的准确含义是
( ( ( echo 1 && false ) && echo 2 ) || echo 3 )
好吧,这里发生了什么?
shell 开始计算
( ... || echo 3 )
,但要做到这一点,它必须首先计算左侧命令。shell 开始计算
( ... && echo 2 )
,但要做到这一点,它必须首先计算左侧命令。shell 开始计算
( echo 1 && false )
,但要做到这一点,它必须首先计算左侧命令。shell 评估
echo 1
哪个总是成功,即以状态代码零退出。echo 1
操作员并不关心打印某些内容的事实&&
,但它解释了输出的第一行,1\n
。第一个操作数的左操作数
( echo 1 && false )
成功,因此 shell 继续计算右操作数false
。这是总是失败的命令,因此&&
整个表达式都会失败。的左操作数
( ... && echo 2 )
已经失败,因此 shell才不是执行echo 2
,并且该表达式本身失败。的左操作数
( ... || echo 3 )
失败,因此 shell做执行echo 3
。此命令会生成第二行输出,但更重要的是对于||
运算符而言,它始终会成功,因此and运算符echo
的整个序列都会成功。&&
||
如果在运行命令后输入 ,
echo $?
您会看到值为零,表明上一个命令成功。
你的第二个例子可以通过上面概述的相同过程进行评估,但让我们详细介绍一下。
echo 2 || echo 3
这比您的第一个示例简单得多。 shell 执行以下步骤。
shell 开始计算
echo 2 || echo 3
,但要做到这一点,它必须首先计算左侧。shell 评估
echo 2
.这将打印您的一个输出行,并成功。shell 继续评估
echo 2 || echo 3
,但现在由于左手成功,状态规则||
根本不评估右手(因此您不会得到另一行输出)。因为左边成功了,所以整个||
表达式也成功了。
这很详细,但我希望它能有所帮助。
答案3
shell 按照严格的从左到右的顺序执行命令(对于 OR 和 AND 列表)。
在此命令中:
echo 1 && false && echo 2 || echo 3
第一个命令是echo 1
.它被执行并且退出状态变为0
(即使它在开始时已经是 0),因为 echo 的退出状态始终为0
。
当找到第一个命令时&&
,退出状态为 0(从上面开始),这意味着执行成功,然后&&
接受并执行下一个命令。
执行时false
,退出状态变为 1(失败)。
找到 next 时&&
,当前退出状态为 1,&&
被拒绝并且下一个命令 ( echo 2
) 不会被执行。
但该行仍然有更多代码,因此 shell 会转到下一项,即||
.作为1
此时的当前退出状态,将被接受并执行||
下一个命令 ( )。echo 3
该命令echo 2 || echo 3
非常容易分析。第一个命令(总是)被执行以获得退出代码。该退出代码是0
,下一个||
被拒绝并且echo 3
不被执行。没有其他需要处理的,行尾。