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

Re: Fw: Submitted: final draft of HOWTO



All of this discussion is in preparation for suggesting specific
additions to the Bash Howto to cover the issue of differing syntax
across processing boundaries in bash.  The point of the back and forth
discussion is to better understand what is really happening and to
develop appropriate example scripts before doing any serious writing.

Paul, Thanks in advance for your response, here's more.

Pal Domokos wrote:
> 
> Hi Patrick,
> 
> Comments to your problem:
> 1. In your first example the $s are missing:
> 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
> (Not that it matters too much...)
> 
Sorry about that.  In an effort to get this to work, I tried a lot of
different variations on syntactic forms, not all of them correct. This
was one of them..  You are right of course, the intended example had the
$i and $j and you are correct that it did not make a difference in the
resulting message for the reason you gave later. 

> 2. Run your program with sh -x and see what it shows:
> $ sh -x a_if.sh
> 
> Why 'if [ $i -eq 1 && $j -eq 2 ]' does not work?
> && is for bash, therefore it tries to evaluate both sides of
> the condition, i.e. both sides should be correct in themselves.
> [ $i -eq 1     is obviously not correct.
> 
> Why 'if [ $i -eq 1 -a $j -eq 2 ]' does work?
> -a is an option for test, therefore in this
> case bash passes the whole condition to test and test processes it.
> 
> That's why this also works:
> if [ $1 -eq 1 ] && [ $2 -eq 1 ]
> (two calls of test)
> 
That's pretty much what I figured. but Oh my that -x is handy.  It
appears to show what bash is evaluating at each step.  What's it doing
exactly, and why can't I find it in the list of options for bash?  does
this feature have a name?


  
My post if you can get through all the verbiage comes to the same
conclusion.
Your more concise version points out that bash is evaluating the
expression [ $i -eq 1 before evaluating &&  is this correct?  Is this
where the message regarding the missing ] is coming from.  What happens
to the rest of the expression, is it just abandoned, because the first
part is "false"?  As a test of this question I modified the test script
yet again:


#!/bin/sh
if [ $1 -eq 1 || $2 -eq 2 ]
then
   echo "i=1 and j=2"
else
   echo "i<> 1 or j<> 2"
fi
 

$ ./a_if.sh 1 1
./a_if.sh: [: missing `]'
./a_if.sh: 1: command not found
i<> 1 or j<> 2   ./a_if.sh 1 1
./a_if.sh: [: missing `]'
./a_if.sh: 1: command not found
i<> 1 or j<> 2   

Note the difference:  bash again complains that the ] is missing from
the part before the || and evaluates the incorrect expression as false. 
because this time we're using || instead of &&, bash continues with the
evaluation in hopes of finding the value true.  In this case a second
error message appears, this one says 1 is an invalid command.  the
evaluation of the second half of the expression attempts to decipher 1
-eq 2 ] as if it were a command.  Of course it fails because 1 is not a
command.

Question:  Is there any legal way to use && in a test command.  Maybe
something with parenthesis so bash evaluates to something that test can
use?



> Well, I'm not a bash guru but I think this is how it works.
> 
> Cheers,
> Pal
> 


> Patrick Callahan <pac1@tiac.net> wrote:
> > 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".
> > >
> >
> > Mike,
> >
> > 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
> > things
> > 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]
> > then
> > fi
> >
> > That's not what really happens.
> >
> > the real syntax of an if command is
> > if bash-condition-expression
> > then
> > fi
> >
> > 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.
> >
> > #!/bin/sh
> > if ,*&^%$#@!
> > then
> >    echo "garbage is true"
> > else
> >    echo "garbage is false"
> > fi
> >
> > $ ./a_if8.sh
> > ./a_if8.sh: ,*: command not found
> > ./a_if8.sh: ^%0@!: command not found
> > garbage is false
> >
> >
> >
> >
> > -pat
> >
> >
> >
> >
> >
> >  >
> > > Another  language element continues to give me trouble.  It is the
> > > combination of conditions in an if statement, and the tutorial does
> > not
> > > go into enough specifics on this point.
> > >
> > > Using && to join two "conditions"  does not work as "expected" when
> > the
> > > 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
> > an
> > > explanation of what is really happening in this case would enhance the
> > > HOWTO.  To most of us from other programming environments $i -eq 1
> > looks
> > > 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
> > does
> > > not.  I'm assuming the construct works if the conditions are
> > "variables"
> > > 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
> > limited
> > > to being used as operators on variables that's ok.  If there's a way
> > to
> > > write a conditional expression using actual conditional expressions
> > that
> > > 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...
> > >
> >
> >
> > From:
> >                "M. Leo Cooper" <thegrendel@theriver.com>
> >
> 
> > Sun 16:35
> >
> >        Subject:
> >                Submitted: final draft of HOWTO
> >  Resent-From:
> >                ldp-discuss@lists.debian.org
> >            To:
> >                ldp-discuss@lists.linuxdoc.org
> >
> >
> >
> >
> > 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
> > attachment
> > to ldp-submit.
> >
> > This document is also downloadable from my web site:
> > http://personal.riverusers.com/~thegrendel/abs-HOWTO-0.1.tar.gz
> >
> > [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
> > Martin.
> >
> > Any comments and constructive criticism would be appreciated.
> >
> > Thanks.
> >
> >
> > Mendel
> >
> >
> > --
> > To UNSUBSCRIBE, email to ldp-discuss-request@lists.debian.org
> > with a subject of "unsubscribe". Trouble? Contact
> listmaster@lists.debian.org
> 
> ____________________________________________________________________
> Get free email and a permanent address at http://www.netaddress.com/?N=1


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


mirror server hosted at Truenetwork, Russian Federation.