我试图理解逻辑运算符优先级如何在 bash 中工作. 例如, 我原以为, 以下命令不会回显任何内容.
true || echo aaa && echo bbb
然而, 与我的期望相反, bbb被打印出来.
有人可以解释一下, 我怎样才能理解复合和 && 和 || bash 中的操作符?
最佳答案
在许多计算机语言中, 具有相同优先级的运算符是 left-associative. 也就是说, 在没有分组结构的情况下, 首先执行最左边的操作. Bash 是这个规则的 no exception.
这很重要, 因为在 Bash,&& 和 || 具有相同的优先权.
那么在你的例子中发生的是最左边的操作 (||) 首先执行:
true || echo aaa
因为真的显然是真的,|| 操作符短路并且整个语句被认为是真实的, 而不需要像您期望的那样评估 echo aaa. 现在仍然要做最正确的操作:
(...) && echo bbb
由于第一个操作被评估为 true(即具有 0 退出状态), 因此就像您正在执行一样
true && echo bbb
所以 && 不会短路, 这就是为什么你看到 bbb 回应.
你会得到相同的行为
false && echo aaa || echo bbb
基于评论的备注
您应该注意, 只有当两个运算符具有相同的优先级时, 才会遵循左关联性规则. 当您将这些运算符与 [[…]] 或((…))等关键字结合使用或使用 – o 和 – a 运算符作为测试或 [命令] 的参数时, 情况并非如此. 在这种情况下, AND(&& 或 – a)优先于 OR(|| 或 – o). 感谢 Stephane Chazelas 澄清这一点.
似乎 in C 和 C 类语言 && 优先级高于 || 这可能就是为什么你期望你的原始结构表现得像
true || (echo aaa && echo bbb).
但是, Bash 不是这种情况, 两个运算符都具有相同的优先级, 这就是 Bash 使用左关联性规则解析表达式的原因. 感谢 Kevin 对此提出的评论.
可能还会出现评估所有 3 个表达式的情况. 如果第一个命令返回非零退出状态, 则为 || 不会短路并继续执行第二个命令. 如果第二个命令以零退出状态返回, 那么 && 也不会短路, 第三个命令将被执行. 感谢 Ignacio Vazquez-Abrams 对此提出的评论.