I am trying to understand how the logical operator precedence works in bash. For example, I would have expected, that the following command does not echo anything.
true || echo aaa && echo bbb
However, contrary to my expectation, bbb
gets printed.
Can somebody please explain, how can I make sense of compounded &&
and ||
operators in bash?
In many computer languages, operators with the same precedence are left-associative. That is, in the absence of grouping structures, leftmost operations are executed first. Bash is no exception to this rule.
This is important because, in Bash, &&
and ||
have the same precedence.
So what happens in your example is that the leftmost operation (||
) is carried out first:
true || echo aaa
Since true
is obviously true, the ||
operator short-circuits and the whole statement is considered true without the need to evaluate echo aaa
as you would expect. Now it remains to do the rightmost operation:
(...) && echo bbb
Since the first operation evaluated to true (i.e. had a 0 exit status), it's as if you're executing
true && echo bbb
so the &&
will not short-circuit, which is why you see bbb
echoed.
You would get the same behavior with
false && echo aaa || echo bbb
Notes based on the comments
[[...]]
or ((...))
or use the -o
and -a
operators as arguments to the test
or [
commands. In such cases, AND (&&
or -a
) takes precedence over OR (||
or -o
). Thanks to Stephane Chazelas' comment for clarifying this point.It seems that in C and C-like languages &&
has higher precedence than ||
which is probably why you expected your original construct to behave like
true || (echo aaa && echo bbb).
This is not the case with Bash, however, in which both operators have the same precedence, which is why Bash parses your expression using the left-associativity rule. Thanks to Kevin's comment for bringing this up.
There might also be cases where all 3 expressions are evaluated. If the first command returns a non-zero exit status, the ||
won't short circuit and goes on to execute the second command. If the second command returns with a zero exit status, then the &&
won't short-circuit as well and the third command will be executed. Thanks to Ignacio Vazquez-Abrams' comment for bringing this up.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments