On 03/28/2018 01:22 PM, Klaus Bartels wrote:
If you execute the following script the result is wrong. It is self explaining:
Sorry, but your script behaves as documented by POSIX.  It is not a bug 
in bash, but in your expectations.
-------------------------------
#
# GNU bash, version 4.4.12(1)-release (x86_64-slackware-linux-gnu)
# Linux ... 4.9.31 #1 SMP Wed Jun 7 14:57:36 CDT 2017 x86_64 Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz GenuineIntel GNU/Linux
#
test a = a && {
   echo this line should be displayed
   test a = b && {
     echo this line should also not displayed, but creates the error
     }
     # echo uncomment this line and all works fine again
   } || {
   echo this line should never be displayed
   }
The overall form of your script is:

pipeline1 && pipeline2 || pipeline3

Note that in shell, && and || are left-associative with EQUAL precedence (this is unlike in C, where && has higher precedence than ||).
In short, pipeline2 is not executed unless pipeline1 has an exit status 
of 0 (which it does); and pipeline3 is not executed unless the construct 
"pipeline1 && pipeline2" has a non-zero exit status (the presence or 
absence of your comment is affecting that; more details below).  The 
exit status of an AND or OR list is the exit status of the last pipeline 
executed in the list, whether or not pipeline3 is executed depends on 
the exit status of pipeline2.
Now, let's investigate pipeline2 in more details - you wrote it as a 
single compound command containing a list; the first list item is the 
echo command (which succeeds in all but corner cases like stdout hitting 
ENOSPC), the second is in the form 'pipeline4 && pipeline5', and then 
your are basing your test on whether there is a comment or a third 
element of another echo.  Comments do not count as a command, so they 
cannot change the exit status; so you are observing different behavior 
based on whether the third echo runs (which changes the overall status 
of pipeline2 to be 0) or is a comment (which leaves the overall status 
of pipeline2 as the exit status of 'pipeline4 && pipeline5').  But 
pipeline4 is something that ALWAYS has non-zero status, and therefore 
pipeline5 is never executed, and the exit status of 'pipeline4 && 
pipeline5' is non-zero.
So back to the overall expression: if pipeline2 has non-zero status, 
then pipeline3 is run, even though that is the echo statement you 
incorrectly surmised would never display.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

Reply via email to