Em muitas linguagens de computador, os operadores com a mesma precedência são associativos à esquerda . Ou seja, na ausência de estruturas de agrupamento, as operações mais à esquerda são executadas primeiro. O Bash é sem exceção desta regra.
Isso é importante porque, no Bash, &&
e ||
têm a mesma precedência.
Então, o que acontece no seu exemplo é que a operação mais à esquerda ( ||
) é executada primeiro:
true || echo aaa
Como true
é obviamente verdadeiro, os curtos-circuitos do operador ||
e toda a instrução são considerados verdadeiros sem a necessidade de avaliar echo aaa
como seria de se esperar. Agora resta fazer a operação mais à direita:
(...) && echo bbb
Desde a primeira operação avaliada como verdadeira (ou seja, com um status de saída 0), é como se você estivesse executando
true && echo bbb
para que &&
não cause curto-circuito, e é por isso que você vê bbb
ecoado.
Você teria o mesmo comportamento com
false && echo aaa || echo bbb
Notas baseadas nos comentários
- Você deve observar que a regra de associatividade à esquerda é somente seguida quando ambos os operadores têm a mesma precedência . Esse não é o caso quando você usa esses operadores em conjunto com palavras-chave como
[[...]]
ou((...))
ou usa os operadores-o
e-a
como argumentos para os comandostest
ou[
. Nesses casos, AND (&&
ou-a
) tem precedência sobre OR (||
ou-o
). Graças ao comentário de Stephane Chazelas para esclarecer este ponto. -
Parece que em C e em linguagens semelhantes a C
&&
tem precedência superior a||
, que é provavelmente por que você esperava que sua construção original se comportasse comotrue || (echo aaa && echo bbb).
Este não é o caso de Bash, no entanto, em que ambos os operadores têm a mesma precedência, razão pela qual o Bash analisa sua expressão usando a regra de associatividade à esquerda. Graças ao comentário de Kevin por mencionar isso.
-
Também pode haver casos em que as expressões todos 3 são avaliadas. Se o primeiro comando retornar um status de saída diferente de zero, o
||
não causará curto-circuito e continuará executando o segundo comando. Se o segundo comando retornar com um status de saída zero, o&&
também não causará curto-circuito e o terceiro comando será executado. Graças ao comentário de Ignacio Vazquez-Abrams por trazer isso à tona.