[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Possible bug in bash
From: |
Greg Wooledge |
Subject: |
Re: Possible bug in bash |
Date: |
Fri, 13 May 2022 23:27:50 -0400 |
On Fri, May 13, 2022 at 10:36:56PM -0400, Dale R. Worley wrote:
> Reading your message, I believe that the rule can be stated as follows,
> and I'd thank you to check it: && and || have the same precedence, and
> they both "associate left". So for example
> x && yy || zz
> is equivalent (as a control structure) to
> { x && yy ;} || zz
Not really. Let's say you have a bunch of commands strung together like
this:
a && b || c && d || e && f || g
We start with the shell's command parser pointing to "a", which I'll
represent like this:
a && b || c && d || e && f || g
^
So, "a" is executed, and this sets the $? special parameter to some value,
either 0 or nonzero. The parser moves to the right and sees "&& b":
a && b || c && d || e && f || g
^^^^
So it checks $?. If $? is 0, then b will be executed. Otherwise, the
parser will keep reading to the right. Next it sees "|| c":
a && b || c && d || e && f || g
^^^^
If $? is nonzero (either from "a" or from "b"), then "c" will be executed.
Otherwise, the parser keeps reading to the right:
a && b || c && d || e && f || g
^^^^
And so on, until the entire line has been processed. Each simple command
in the line is either executed, or not, depending on the current value
of $? and the operator which precedes it.
That's why this has no equivalence to a regular "if/then/else" command.
The implementation is just entirely different.
Here's an actual example:
unicorn:~$ false && true || true && echo a || false && echo b
a
b
The first "false" is executed no matter what; this sets $? to 1. The
parser looks at "&& true" and skips it because $? is nonzero. So it
looks at "|| true", and runs that because $? is nonzero. Now $? is 0.
Next up is "&& echo a", and since $? is 0, bash runs that echo. This
sets $? to 0 (because the echo succeeded), so "|| false" is skipped.
The parser finally ends on "&& echo b", and since $? is 0, that echo
is also executed.
In real life, there is no reason to write code like this. It's horrible
and confusing. Just don't do it.