On Wed, Apr 04, 2007 at 08:17:22PM +0100, Chris G wrote:
On Wed, Apr 04, 2007 at 04:43:44PM +0100, Brett Parker wrote:
On Wed, Apr 04, 2007 at 04:11:56PM +0100, Chris G wrote:
I want to group some logic in a test in a bash script.
I.e. I am trying to write something like:-
if [ this -a (that -o theOther) ]
but bash always complains about 'syntax error'. I have reduced the code to the trivial:-
home$ if [ ( true ) ]; then
but still get the syntax error.
According to the man page for test the format is:-
( EXPRESSION ) EXPRESSION is true
I *think* that is trying to tell me that I can use () to group parts of what is inside the []. However, as I said, it refuses to work as I expected. I have tried all combinations of spaces etc. either side of the () but it still just gives a syntax error.
Is this just a case where the () are punctuation in the man page rather than real () to use in the expression? Or am I doing something obvious wrong? (probably!).
Well, afaik, -a is a file test, so that's probably not what you want...
-a is a logical AND, similarly -o is a logical OR.
They're overloaded terms, in bash, at least (under the CONDITIONAL EXPRESSIONS section): -a file True if file exists.
-o optname True if shell option optname is enabled. See the list of options under the description of the -o option to the set builtin below.
(And yes, by default, bash uses it's builtins, not test, and so these really are what they say they are, except when you're using them between expressions, at which point they change meaning to logical AND and logical OR, which is the only meaning that have in "test")
Whereas && and || are much more logical (and work in more places, in my experience).
Also, you don't say if "this", "that" and "theOther" are commands or not... if they are, you probably don't want to be using test to work it out, and something more like...
They were just placeholder expressions.
if ( true && ( false || true ) ); then echo yes; fi
Ah, but in that case the () are just sub-shells aren't they?
Yes, but as you never actually qualified what you were trying to do, that's perfectly valid. Of course, if you want to use less subshells, the above could be better written as: if true && ( false || true ); then echo yes; fi
If the exit of either the false or the true is true (i.e. $? = 0), and the true has a return code of 0, the if will be true.
If you really don't like subshells, then you can group the list in a set of braces as such... if true && { false || true; }; then echo yes; fi
Note: the ; before the closing brace is important, as is the white space after the { and before the }.
if they're variables, then something more like:
if [ this ] && ( [ that ] || [ theOther ] ); then echo yes; fi
Would be your friend.
and that works nicely, and looks very similar to the external program example, making it easier to chop and change between the two.
brettp@erwin:~$ this=0 brettp@erwin:~$ if [ $this == 0 ] && ([ $this == 1 ] || [ $this == 0 ]); then echo yes; fi yes brettp@erwin:~$ if [ $this == 0 ] && ([ $this == 1 ] || [ $this == 1 ]); then echo yes; fi brettp@erwin:~$
Cheers,