逻辑运算符与分号的优先级

逻辑运算符与分号的优先级

如果我在 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无论commandAcommandB失败或成功都会被执行。

分号只是一个分隔符,使命令顺序执行。我能看到的唯一commandC会失败的场景是如果commandA或是commandBexit命令(或任何强制影响工作流程的命令,如 // / (或调用这些命令的函数)returnbreakcontinueexec

场景一:commandAexit

[root@host ~]# exit && echo "HI"; echo "test"
logout
[user@host ~]$

场景2:commandBexit

[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 不会退出。ifelif&&或者||列出除最后一个命令之外的命令&&||、管道中除最后一个命令之外的任何命令,或者如果命令的返回值与 反转!

- 从重击(1)

因此,如果commandA失败,只会导致commandB不被执行,因为commandA后面是&&。但如果commandB运行失败,它会导致 shell 退出,因为它 ( commandB) 跟在 (final) 后面&&

相关内容