218

I'm trying to write a script that will check two error flags, and in case one flag (or both) are changed it'll echo-- error happened. My script:

my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" &&     "$my_error_flag_o"="2" ]]; then
    echo "$my_error_flag"
else
    echo "no flag"
fi

Basically, it should be, something along:

if ((a=1 or b=2) or (a=1 and b=2))
  then
     display error
else
     no error
fi

The error I get is:

 line 26: conditional binary operator expected
 line 26: syntax error near `]'
 line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'

Are my brackets messed up?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Simply_me
  • 2,840
  • 4
  • 19
  • 27

4 Answers4

330

Use -a (for and) and -o (for or) operations.

tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

Update

Actually you could still use && and || with the -eq operation. So your script would be like this:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
      echo "$my_error_flag"
else
    echo "no flag"
fi

Although in your case you can discard the last two expressions and just stick with one or operation like this:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ]; then
      echo "$my_error_flag"
else
    echo "no flag"
fi
BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
mkhatib
  • 5,089
  • 2
  • 26
  • 35
  • thank you for the quick answer, but in case both flags are true, won't it violate the condition? – Simply_me Apr 24 '13 at 22:45
  • 4
    @Simply_Me: No, a logical OR is true if either *or both* of its operands are true. You're thinking of "exclusive or" (XOR), which is true if exactly one of its operands is true. (Actually, there are versions of XOR that work on more than 2 operands, in which case it's true if an odd number of operands are true.) – Gordon Davisson Apr 24 '13 at 23:24
  • 4
    BTW, problems in the original code include using `[` and `]` for grouping (they don't do that), and failing to put spaces around the operator (e.g. `"$my_error_flag"="1"`), which prevents the shell from recognizing it as an operator at all. Please read [BashFAQ #17 (on grouping)](http://mywiki.wooledge.org/BashFAQ/017) and [#31 (on the difference between different types of test expression)](http://mywiki.wooledge.org/BashFAQ/031). Actually, in this case it would be even easier to use an [arithmetic expression](http://mywiki.wooledge.org/ArithmeticExpression). – Gordon Davisson Apr 24 '13 at 23:39
  • Thank you @GordonDavisson and for your detailed answers and references. – Simply_me Apr 25 '13 at 00:53
  • Thank you @mkhatib and for your detailed answers and references. – Simply_me Apr 25 '13 at 00:54
  • 10
    `-a` and `-o` are considered obsolete by the [POSIX specification](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128_16); use separate tests combined with `||` as in the update. – chepner Apr 25 '13 at 12:13
  • 1
    No need to group using subshells, normally grouping using `{}` should also be possible. – phk Sep 23 '16 at 16:40
  • 2
    to add to phk's comment above, ( ) is launching subshells in bash, which can have all sorts of subtle [probably unwanted] effects. – brett Apr 20 '18 at 11:19
92

You can use either [[ or (( keyword. When you use [[ keyword, you have to use string operators such as -eq, -lt. I think, (( is most preferred for arithmetic, because you can directly use operators such as ==, < and >.

Using [[ operator

a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
     echo "Error"
else
     echo "No Error"
fi

Using (( operator

a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
     echo "Error"
else
     echo "No Error"
fi

Do not use -a or -o operators Since it is not Portable.

Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
10

Please try following

if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
    echo "WORKING"
else
    echo "Out of range!"
pacholik
  • 8,607
  • 9
  • 43
  • 55
Manash Nath
  • 109
  • 1
  • 2
1

You can get some inspiration by reading an entrypoint.sh script written by the contributors from MySQL that checks whether the specified variables were set.

As the script shows, you can pipe them with -a, e.g.:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi
Daniel Andrei Mincă
  • 4,446
  • 2
  • 19
  • 30
  • 5
    `-a` is marked as obsolescent in the current version of the POSIX `test` standard; see the `OB` markers at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html. Use `[ -z "$FOO" ] && [ -z "$BAR" ]` to have more reliable code. – Charles Duffy Aug 10 '18 at 17:18