help-bash
[Top][All Lists]
Advanced

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

Re: [Help-bash] Syntax for if test


From: Greg Wooledge
Subject: Re: [Help-bash] Syntax for if test
Date: Mon, 5 Dec 2011 10:51:51 -0500
User-agent: Mutt/1.4.2.3i

On Mon, Dec 05, 2011 at 09:21:36AM -0600, Bill Gradwohl wrote:

Let's start here:

> Lastly, I've read up on [[ ]] numerous times in man bash and I can't quite
> wrap my head around it. Can someone point at an alternate explanation on
> the features and benefits of using [ ] vs [[ ]] ?

http://mywiki.wooledge.org/BashFAQ/031


> What I want to say is :
> if a is true or (b is true and c is true) then do something.

if [[ a || b && c ]]; then
  something
fi

Bearing in mind that && has a higher precedence than ||, making the
parentheses redundant.  For clarity, you could add them:

if [[ a || (b && c) ]]; then
  something
fi

> I can't seem to get the syntax correct using a standard [ ] notation.

It cannot be done portably with a *single* [ ... ] command.  The syntax
just isn't that flexible.  If you want POSIX compatibility, you must
use several [ ... ] commands instead:

if [ a ] || [ b ] && [ c ]; then
  something
fi

If you require grouping, then:

if [ a ] || { [ b ] && [ c ]; }; then
  something
fi

Note the semicolon inside the curly braces.  It's required in a single-line
command grouping.

> if [ $(some executable) -o ( $(some executable) -a $(some executable ) ];

Do not attempt to use -o or -a.  Ever.  Either use [[ a && b ]] or use
[ a ] && [ b ].  One rule of thumb here is that if you are writing for
POSIX you should use [ a ] && [ b ]; and if you are writing for bash, then
you should use [[ a && b ]].

> Also, man bash says:
> ( expression )
>                      Returns the value of expression.  This may be used to
> override the normal precedence of operators.
> 
> No matter what I try I can't seem to get the syntax correct to use ( ) as
> shown above.

It works fine in [[ ... ]].  If you want to use it inside [ ... ] then
you would have to escape it, but please, don't do that.  Just use multiple
[ ... ] commands instead.  That way your code will be portable and readable.

> if [ $(echo "${templateMachine}"|egrep -q '\.') -a $(grep -q
> "${templateMachine}" /etc/hosts|grep -q $(hostname -s)) ] || [
> "${templateMachine}" == $(hostname -s) ]; then

grep -q | grep -q is not right.  The first one won't write anything for
the second one to read.

do_it=0
if [[ $templateMachine = "$(hostname -s)" ]]; then
        do_it=1
elif [[ $templateMachine = *.* ]] &&
   grep "$templateMachine" /etc/hosts | grep -q "$(hostname -s)"; then
        do_it=1
fi
if ((do_it)); then
    something
fi

That's how I'd write it, assuming I fixed your greps correctly.  You
should choose a more meaningful flag variable name than do_it; I can't
pick one because I don't know what it's doing.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]