Date: Fri, 13 May 2022 22:36:56 -0400 From: "Dale R. Worley" <wor...@alum.mit.edu> Message-ID: <87ilq8hmbb....@hobgoblin.ariadne.com>
| Reading your message, I believe that the rule can be stated as follows, | and I'd thank you to check it: OK | && and || have the same precedence, and they both "associate left". That is correct, I believe ... I sometimes have trouble wrapping my head around formal mathematical definitions. But if you are going to state it that way, you should probably also add that short circuit evaluation is required, that is, as binary operators, the RHS is never evaluated if the result is known from the LHS. (This is not just an optimisation, it is a requirement.) | So for example A better example might be, that for any pipelines a b c d and where X Y and Z each represents one of the control operators && or || in any combination a X b Y c Z d is equiv to: { { a X b; } Y c; } Z d And just as a hint, far and away the best/safest way to make use of these operators is when only one of them is used (any number of times) in one and-or list. So: a && b && c && d && e && ... causes a b c d e ... to be executed, in sequence, until one of them "fails" (that is, exits with a status that is not zero), after which none of the rest is executed (or evaluated at all). The exit status of the list is (as always in and-or lists) that of the last command executed, so is 0 here only if every command was executed, and all exited with status 0. And: a || b || c || d || e || ... causes a b c d e ... to be executed, in sequence, until one of them "succeeds" (exits with status 0), after which none of the rest is executed (or evaluated). The exit status of the list works the same way, but here will be 0 unless every command in the list was executed with non-zero status returned every time. The idiom command || : is how one says "I don't care about the exit status of command". Mixing && and || in the same and-or list takes very careful thought, even very experienced sh programmers mess that up more often than you'd imagine. Much better to use the equiv form, with the explicit grouping, the: a X b Y c Z d form is one and-or list, and if X Y and Z are not all the same, will often, if you are not very careful, have unanticipated results. Write it as: { { a X b; } Y c; } Z d and now there are 3 independant (binary) and-or lists, which is much easier to reason about. (It is reasonable to expand any of those 3 and-or lists to more terms, provided each makes use of only one of the two possible operators, in the innermost, every operator is X, etc.) kre Bonus extra: A common error is to end a function with something like: $verbose && echo function finished That is almost always wrong, as it causes the function to return non-zero status if verbose=false. That is, while you are debugging the script, with verbose=true it all works as intended (perhaps add "eventually" there) but as soon as you set verbose=false, things change. If written as the seemingly equivalent: if $verbose; then echo function finished; fi we do not get that issue, the function will always return a 0 status if it gets that far (and that is its final command). Please do not treat this as an endorsement of "echo", using printf would be better, nor for not quoting var expansions. It is intended as a reinforcement of the: if you mean 'if' write 'if' not '&&' message.