david
david

Reputation: 761

Compound 'if' statements with multiple expressions in Bash

I would like to recreate something like this

if ( arg1 || arg2 || arg 3) {}

And I did got so far, but I get the following error:

line 11: [.: command not found

if [ $char == $';' -o $char == $'\\' -o $char == $'\'' ]
then ...

I tried different ways, but none seemed to work. Some of the ones I tried.

Upvotes: 20

Views: 31103

Answers (4)

chunky_pie
chunky_pie

Reputation: 41

In bash, to group conditionals using the [ ] construct you must surround each group using parenthesis. Each opening/closing parenthesis must be escaped and preceded/succeeded with a white space. See below:

if [ \( "$char" = "$;" \) -o \( "$char" = "$\\" \) -o \( "$char" = "$\" \) ]

As such, it's definitely best to follow everyone elses advice and use bash's newer [[ ]] construct. Lastly, as I understand it == is a relational operator intended to be used with-in arithmetic expressions. i.e. -

$((3==4))

Cameron Newham and Bill Rosenblatt, "Learning the bash Shell" Jan.1998

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295363

For Bash, you can use the [[ ]] form rather than [ ], which allows && and || internally:

if [[ foo || bar || baz ]] ; then
  ...
fi

Otherwise, you can use the usual Boolean logic operators externally:

[ foo ] || [ bar ] || [ baz ]

...or use operators specific to the test command (though modern versions of the POSIX specification describe this XSI extension as deprecated -- see the APPLICATION USAGE section):

[ foo -o bar -o baz ]

...which is a differently written form of the following, which is similarly deprecated:

test foo -o bar -o baz

Upvotes: 33

codeforester
codeforester

Reputation: 42999

Bash's [[ ]] and (( )) are more powerful and flexible than [ ].

  • [[ ]] is for strings and (( )) is for integer logic and arithmetic
  • && and || operators can be used inside [[ ]] and (( )), and () can be used for grouping
  • No need to quote variable expansions inside [[ ]] or (( )) - Bash doesn't do word splitting or globbing in these contexts
  • Inside (( )), there is no need for a $ behind variable names to expand them
  • [[ ]] and (( )) can span multiple lines, without the need for a line continuation with \

Using these, we can write clean, readable, and more reliable code.

Examples

Compound statements with integers

a=1 b=2 c=3
((a == 2 || (b == 2 && c == 3))) && echo yes                   # yields yes

Compound statements with strings

x=apple y=mango z=pear
[[ $x == orange || ($y == mango && $z == pear) ]] && echo yes  # yields yes

[ equivalents for the above statements, using {}

[ "$a" -eq 2 ] || { [ "$b" -eq 2 ] && [ "$c" -eq 3 ]; }
[ "$x" == orange ] || { [ $y == mango ] && [ "$z" == pear ]; }

Related

Upvotes: 11

kojiro
kojiro

Reputation: 77089

Charles' answer is correct in that it shows you how to do logical operations on commands within (and without, for that matter) an if statement, but it looks more like you want to use case here:

case $char in
    \;|\\|\') echo found;;
    *) echo 'not found';;
esac

Upvotes: 4

Related Questions