[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fw: Submitted: final draft of HOWTO

Mike & Penny Novack wrote:
> Because my personal coding style (in any language) is to always
> explicitly specify the order of evaluation I never seem to get involved
> with these questions. Have you considered what the relative order of
> operator precedence might be?. A "condition" is after all only a value
> (typically zero => false, anything else true). Try inserting whatever
> serves as "parentheses" around each conditional expression and see what
> happens to the evaluation.
> My suspicion is that "-a" and "-o" work because they have lower
> precedence than any relation that might appear inside a "condition".
> What happens if you start out example "A" with i=1;j=1 (adjusting the
> other items accordingly). Does it now work? That might be the case if
> the precedence of "&&" is equal or greater than that of "-eq".


That's a great insight.  

There's some info on how bash handles precedence and the order of
evaluation of things in bash. It didn't seem to help but a few
experiments clarified what's going on.

Its an interesting problem.  Bash the language vs Bash the executor of
other commands with different languages.  Where does the line get drawn
between various parts of the "language space".  

Incidently, this is the exact problem I'm struggling with trying to use
the Python - PMW - Tkinter - tkinter - tk packages to build a GUI.  It's
difficult to discern which level of interface and which a particular
syntic form  applies.  Both bash and python cross linguistic borders. 
This can make a perfectly ordinary conceptual structure difficult to
implement for those not used to the border crossings.  We're accustomed
to binding values, types and methods across interfaces, but the
resulting syntactic ambiguity when different languages are used on
either side of the interface is something to consider.  Something to
think about for Bash 3.0:  the problem of binding syntax across an
interface.  Has anyone else thought about this?

Anyway to get some info on this I tried a few potential variations.  I
tried putting the expressions in parenthesis and brackets but that
didn't work.

if [ ( $1 -eq 1 ) && ( $2 -eq 1 ) ]
if [ [ $1 -eq 1 ] && [ $2 -eq 1 ] }

The problem with bash is that it calls lots of other programs to do
like /etc/bin/test.  I think the && and || operators exist only in bash
and not in test.
expressions like [ $1 && $2 ] work because bash calculates $1 && $2 and
passes the result of the calculation to test.
with expressions like [ $1 -eq 1 && $2 -eq 1 ] bash doesn't do the
arithmetic right and what gets passed to test somehow includes the
closing bracket, as if it were part of the conditional expression.  it
would be interesting to see if test is actually getting passed anything
or if the whole test is failing due to a parsing error and returning 1
to the if.  In case of an error, if seems to be getting the value false.

That seems to be what's going on.

one more test revealed a solution 

if [ $1 -eq 1 ] && [ $2 -eq 1 ] operated correctly 

Although you could easily come to the conclusion reading the bash manual
that the syntax of an if statement in bash is

if [conditional-expression] 

That's not what really happens.

the real syntax of an if command is 
if bash-condition-expression

and [ condition ] is just one kind of bash-conditional-expression.  In
fact, [ is a separate program that takes values provided by the shell as
arguments.  [  has its own syntax for expressions contained in its
arguments and returns a result.  in fact, [ or if you prefer /bin/test
just processes its command arguments whatever they are.  before [ gets
its arguments, bash applies its rules to whatever is in between the
square brackets.  so the expression as originally stated was being
evaluated as follows by bash, before passing it as arguments to [.  Bash
is probably evaluating the elements of the command line containing the
if statement sequentially.

[ $1 -eq 1 && $2 -eq 1 ]

  [ 1 -eq 1 && 1 -e1 1 ]
  [ 1 -eq (1 && 1) -eq 1 ]
  [ 1 -eq     1    -eq 1 ]

What the error message ./a_if.sh: [: missing `]'  indicates is that bash
probably prepared to pass the following to test:

   1 -eq 1 -eq ] 

This is not particularly meaningful as input to test, but that doesn't
matter, I think test doesn't even get called.  bash next compained that
the open [ of the test command was missing a closing bracket.  The
missing bracket is the one bash was preparing to send to or may have
actually sent to /bin/test in its arguments.

The if statment itself behaves as if it got a false from the whole
expression.  Even when an if statment contains garbage, bash continues
with the if.

if ,*&^%$#@!
   echo "garbage is true"
   echo "garbage is false"

$ ./a_if8.sh
./a_if8.sh: ,*: command not found
./a_if8.sh: ^%0@!: command not found
garbage is false


> Another  language element continues to give me trouble.  It is the
> combination of conditions in an if statement, and the tutorial does
> go into enough specifics on this point.
> Using && to join two "conditions"  does not work as "expected" when
> elements combined with && and || are not variables, but "conditions".
> There's an element of syntax that I'm missing to make Example A work
> correctly, and no reference I've been able to find shows what it is or
> explains the difference between && and || on one hand and -a and -o on
> the other.  I think your howto would be an excellent place to get into
> this issue.
> Example A:
> #!/bin/sh
> # using && to join "conditions" as shown does not work properly
> i=1;j=2
> if [ i -eq 1 && j -eq 2 ]
> then
>    echo "i=1 and j=2"
> else
>    echo "i<> 1 or j<> 2"
> fi
> $ chmod +x a_if.sh
> $ ./a_if.sh
> ./a_if.sh: [: missing `]'
> i<> 1 or j<> 2
> note the error message and incorrect operation in the version of the
> script using && to join two "conditions"
> Example B:
> #!/bin/sh
> # using -a to join two conditions using "and" does work properly
> i=1;j=2
> if [ $i -eq 1 -a $j -eq 2 ]
> then
>    echo "i=1 and j=2"
> else
>    echo "i<> 1 or j<> 2"
> fi
> Executing
> $ ./a_if3.sh
> not i or not j
> This use of -a or -o working in the above construct seems to conflict
> with the following from the bash manual and from the HOWTO.  I think
> explanation of what is really happening in this case would enhance the
> HOWTO.  To most of us from other programming environments $i -eq 1
> like a condition, so we need an explanation of why the construct as
> written in example A does not work while the construct in example B
> not.  I'm assuming the construct works if the conditions are
> and not conditional expressions, at least conditional expressions as
> written in Example A:  We need advice on what exact syntax to use to
> accomplish the intent expressed in example A.  If && and || are
> to being used as operators on variables that's ok.  If there's a way
> write a conditional expression using actual conditional expressions
> will be properly combined using && or || we'll need an example of that
> too.
> What we have in the Bash Reference and the HOWTO does not address this
> issue properly, or if it does, the information is not presented in an
> order that will allow it to be found easily.
> &&
>        and (logical)
>         if [ $condition1 && $condition2 ]
>         # if both condition1 and condition2 hold true...
> ||
>        or (logical)
>         if [ $condition1 || $condition2 ]
>         # if both condition1 or condition2 hold true...

               "M. Leo Cooper" <thegrendel@theriver.com>
Sun 16:35

               Submitted: final draft of HOWTO

I have submitted the final draft of my "Advanced Bash-Scripting HOWTO",
version 0.1, to the group by sending it as as a tarballed file
to ldp-submit.

This document is also downloadable from my web site:

[125 k]

The tarball on my site also has the HTML conversion of the document. The
document itself is, of course, in Docbook/SGML, thanks to Philippe

Any comments and constructive criticism would be appreciated.



To UNSUBSCRIBE, email to ldp-discuss-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org