tags:

views:

60

answers:

3
[root@jiaoyou ~]# test 1 = 1 -a 0 = 1
[root@jiaoyou ~]# if [1 = 1 -a 0 = 1]then echo 1;else echo 2;fi
-bash: syntax error near unexpected token `else'

Why test doesn't give any output and the if statement fails?

Can someone point out what's wrong here?

UPDATE

Can someone illustrate how to simulate complex expressions like 1=1 and (0=1 or 1=1) with [[?

+4  A: 

Return codes are not printed; you must echo the value of $? in order to see it.

[ is a command. Just as you don't write echoHelloworld, you can't write [1 ....

Ignacio Vazquez-Abrams
I just tried `echo $?` but find `test 1 = 1 -a 0 = 1` returns true,while in fact `1=1 and 0=1` should be false,right?
httpinterpret
And I also tried ` if [ 1 = 1 -a 0 = 1 ]then echo 1;else echo 2;fi` but still get a syntax error.
httpinterpret
@httpinterpret: You need a semicolon here: `]; then`. When I do `echo $?` after `test 1 = 1 -a 0 = 1` I get "1" which is false.
Dennis Williamson
No, 0 is success, 1 is failure. `test 1 = 1 -a 0 = 1` returns 1.
Matthew Flaschen
@httpinterpret: Try `false; echo $?` - you will get "1", then try `true; echo $?` - you will get "0".
Dennis Williamson
Oh,I see now.Finally,how to simulate `1=1 and (0=1 or 1=1)` in `test`?the problem is how to denote `()`.
httpinterpret
You can't, in `test`. Use `[[` instead.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams,can you elaborate how to use `[[` to achieve that?
httpinterpret
Open up a terminal and type `help [[` at the bash prompt.
Ignacio Vazquez-Abrams
httpinterpret
Of course not. You're still using `test`.
Ignacio Vazquez-Abrams
Can you give a demo?Thanks a ton ...
httpinterpret
A: 

As @IgnacioVazquez-Abrams correctly states, test just sets the error code.

That said, here's a nice bash-ism for quickly checking the error value:

test [ expr ] && echo SUCCESS || echo FAIL

Due to how && and || short circuit, that will output SUCCESS or FAIL depending on whether test returns 0 or non-0.

R Samuel Klatchko
httpinterpret
R Samuel Klatchko
+1  A: 

There are several equivalent ways of doing the test you're looking for. First, essentially the way you're doing it, but with the syntax fixed (added required spaces around the parameters to the [ (aka test) command, and a ; between ] and then):

if [ 1 = 1 -a 0 = 1 ];then echo 1;else echo 2;fi

Here's a version with explicit grouping in the expression; note that the parentheses have to be escaped because they're special characters in the shell, but in this case we want them passed to the [ command as arguments:

if [ \( 1 = 1 \) -a \( 0 = 1 \) ];then echo 1;else echo 2;fi

Another version with explicit grouping, this time using two separate [ commands connected with bash's && operator (note that this can also connect other commands):

if [ 1 = 1 ] && [ 0 = 1 ];then echo 1;else echo 2;fi

And finally, a couple of examples using bash's [[ operator instead of the [ command; note that [[ isn't a command, so its expression isn't parsed as command arguments, allowing it a more intuitive syntax (e.g. allowing && and || as operators, and parentheses and !<> comparisons without escaping):

if [[ 1 = 1 && 0 = 1 ]];then echo 1;else echo 2;fi
if [[ ( 1 = 1 ) && ( 0 = 1 ) ]];then echo 1;else echo 2;fi

Some more notes/warnings: the = operator being used in all of these examples does string comparisons rather than numeric comparison (i.e. [ 1 = 01 ] is false); if you want numeric comparison use -eq instead (similarly, < and > are string comparisons, while -lt and -gt are numeric). Also, if you're comparing strings that include spaces, '[' can mistake the string for part of the expression under some circumstances (esp. if you don't have the strings wrapped in double-quotes); as far as I know [[ never has this problem. Overall, if you're using shells that support [[, it's much easier to deal with than [.

Gordon Davisson