如果我在 bash 中写一行像这样会发生什么
commandA && commandB ; commandC
如果commandA
失败,会commandC
被处决吗?
答案1
是的,您可以轻松地自己检查:
$ non-existent-command && echo hi ; echo after semicolon
bash: non-existent-command: command not found
after semicolon
其中man bash
写道:
命令之间用 ; 分隔依次执行; shell 依次等待每个命令终止。
答案2
根据 bash 手册页
[L]ist 运算符、&& 和 ||具有同等优先级,后跟 ;和 &,具有相同的优先级。
在实践中,这归结为谁关心返回结果。如果立即需要结果,则具有更高的优先级。
答案3
commandC
无论commandA
或commandB
失败或成功都会被执行。
分号只是一个分隔符,使命令顺序执行。我能看到的唯一commandC
会失败的场景是如果commandA
或是commandB
exit
命令(或任何强制影响工作流程的命令,如 // / (或调用这些命令的函数)return
)break
:continue
exec
场景一:commandA
是exit
[root@host ~]# exit && echo "HI"; echo "test"
logout
[user@host ~]$
场景2:commandB
是exit
[root@host~]# echo "HI" && exit; echo "test"
HI
logout
[user@host ~]$
长话短说: 不是说那些字符有优先级吗?它们的含义不同。一个是逻辑运算符,另一个是列表终止符。
相关内容:
shell 的控制和重定向运算符是什么? 这个答案很好地解释了 bash 操作符。引用一下答案的一小段:
;
:将在另一个命令完成后运行一个命令,无论第一个命令的结果如何。command1 ; command2
首先
command1
是在前台运行,一旦完成,command2
将运行。不在字符串文字中或在某些关键字之后的换行符是 不是相当于分号运算符。分隔的简单命令列表
;
仍然是列表- 就像在 shell 的解析器中一样,在执行之前仍然必须继续读入;
分隔简单命令后面的简单命令,而换行符可以分隔整个命令列表或列表列表。区别很微妙,但很复杂:假设 shell 之前没有读取换行符后的数据的命令,则换行符标记 shell 可以开始评估它已经读入的简单命令的点,而分号则;
可以不是。
shell 脚本中行尾的分号是多余的吗? 引用一下答案:
行末尾的单个分号是多余的,因为换行符也是命令分隔符。
case
特别需要在每个模式块中最后一个命令的末尾使用双分号;help case
详情请参阅 。
答案4
正如其他帖子所说,简短的回答是“是的,commandC
无论发生什么,都会被处决。”
作为恩维尔德纳探索,更长的答案是,“是的,commandC
无论发生什么,只要 shell 仍然处于可以执行的状态,就会执行commandC
。换句话说,shell 不会继续执行超出
commandA && commandB ; command
命令行而不执行commandC
。”
简单地说,如果commandA
(或commandB
) 是kill -KILL $$
或其他终止或削弱 shell 或中断命令流的东西,则commandC
不会执行。 (显然,我们在这里讨论的是边缘情况。)如果set -e
(或者等效地,set -o errexit
) 已发出,行为会略有不同:
- 如果
commandA
失败,commandC
将被执行(但commandB
不会被执行)。 - 如果
commandA
成功,则将commandB
被执行。- 如果
commandB
成功,则将commandC
被执行。 - 如果
commandB
失败,shell 将退出,并commandC
会不是被处决。
- 如果
该errexit
选项指定如果任何命令(任何“管道”)失败,shell 将退出,但有一些例外:
while
如果失败的命令是紧跟在or关键字之后的命令列表的一部分、是在或保留字until
之后的测试的一部分、是在 a 中执行的任何命令的一部分,则 shell 不会退出。if
elif
&&
或者||
列出除最后一个命令之外的命令&&
或||
、管道中除最后一个命令之外的任何命令,或者如果命令的返回值与 反转!
。- 从重击(1)
因此,如果commandA
失败,只会导致commandB
不被执行,因为commandA
后面是&&
。但如果commandB
运行失败,它会导致 shell 退出,因为它 ( commandB
) 跟在 (final) 后面&&
。