Differences between revisions 7 and 8
Revision 7 as of 2013-07-26 22:20:03
Size: 2443
Comment: correction on &&/|| precedence.
Revision 8 as of 2015-03-05 00:38:55
Size: 2483
Editor: izabera
Comment: syntax hl
Deletions are marked like this. Additions are marked like this.
Line 5: Line 5:
{{{
    # Bourne
    if commandA && commandB || commandC; then
    ...
{{{#!highlight bash
# Bourne
if commandA && commandB || commandC; then
...
Line 10: Line 10:
    # or with test(1) calls:
    if [ testA ] && [ testB ] || [ testC ]; then
    ...
# or with test(1) calls:
if [ testA ] && [ testB ] || [ testC ]; then
...
Line 20: Line 20:
{{{
    # Bourne
    if commandA && { commandB || commandC; }; then
    ...
{{{#!highlight bash
# Bourne
if commandA && { commandB || commandC; }; then
...
Line 33: Line 33:
{{{
    # Bash/ksh/zsh
    if (( (n>0 && n<10) || n == -1 ))
    then echo "0 < $n < 10, or n==-1"
    fi
{{{#!highlight bash
# Bash/ksh/zsh
if (( (n>0 && n<10) || n == -1 ))
then echo "0 < $n < 10, or n==-1"
fi
Line 41: Line 41:
{{{
    # Bash/ksh/zsh
    if [[ ( -f $localconfig && -f $globalconfig ) || -n $noconfig ]]
    then echo "configuration ok (or not used)"
    fi
{{{#!highlight bash
# Bash/ksh/zsh
if [[ ( -f $localconfig && -f $globalconfig ) || -n $noconfig ]]
then echo "configuration ok (or not used)"
fi
Line 50: Line 50:
{{{
    [ a = a ] || [ b = c ] && [ c = d ]
{{{#!highlight bash
[ a = a ] || [ b = c ] && [ c = d ]
Line 56: Line 56:
{{{
    { [ a = a ] || [ b = c ]; } && [ c = d ]
{{{#!highlight bash
{ [ a = a ] || [ b = c ]; } && [ c = d ]
Line 62: Line 62:
{{{
    [[ a = a || b = c && c = d ]]
{{{#!highlight bash
[[ a = a || b = c && c = d ]]
Line 68: Line 68:
{{{
    [[ a = a || ( b = c && c = d ) ]]
{{{#!highlight bash
[[ a = a || ( b = c && c = d ) ]]
Line 75: Line 75:
{{{
    n=3
    if [[ $n>0 && $n<10 ]]
    then echo "$n is between 0 and 10"
    else echo "ERROR: invalid number: $n"
    fi
{{{#!highlight bash
n=3
if [[ $n>0 && $n<10 ]]
then echo "$n is between 0 and 10"
else echo "ERROR: invalid number: $n"
fi

How can I group expressions in an if statement, e.g. if (A AND B) OR C?

The portable (POSIX or Bourne) way is to use multiple test (or [) commands:

   1 # Bourne
   2 if commandA && commandB || commandC; then
   3 ...
   4 
   5 # or with test(1) calls:
   6 if [ testA ] && [ testB ] || [ testC ]; then
   7 ...

When they are shell operators between commands (as opposed to the [[...]] operators), && and || have equal precedence, so processing is left to right.

If we need explicit grouping, then we can use curly braces:

   1 # Bourne
   2 if commandA && { commandB || commandC; }; then
   3 ...

What we should not do is try to use the -a or -o operators of the test command, because the results are undefined.

BASH, zsh and the KornShell have different, more powerful comparison commands with slightly different (easier) quoting:

Examples:

   1 # Bash/ksh/zsh
   2 if (( (n>0 && n<10) || n == -1 ))
   3 then echo "0 < $n < 10, or n==-1"
   4 fi

or

   1 # Bash/ksh/zsh
   2 if [[ ( -f $localconfig && -f $globalconfig ) || -n $noconfig ]]
   3 then echo "configuration ok (or not used)"
   4 fi

Note that contrary to the && and || shell operators, the && operator in ((...)) and [[...]] has precedence over the || operator (same goes for ['s -a over -o), so for instance:

   1 [ a = a ] || [ b = c ] && [ c = d ]

is false because it's like:

   1 { [ a = a ] || [ b = c ]; } && [ c = d ]

(left to right association, no precedence), while

   1 [[ a = a || b = c && c = d ]]

is true because it's like:

   1 [[ a = a || ( b = c && c = d ) ]]

(&& has precedence over ||).

Note that the distinction between numeric and string comparisons is strict. Consider the following example:

   1 n=3
   2 if [[ $n>0 && $n<10 ]]
   3 then echo "$n is between 0 and 10"
   4 else echo "ERROR: invalid number: $n"
   5 fi

The output will be "ERROR: ....", because in a string comparision "3" is bigger than "10", because "3" already comes after "1", and the next character "0" is not considered. Changing the square brackets to double parentheses (( makes the example work as expected.


CategoryShell

BashFAQ/017 (last edited 2022-10-20 20:40:35 by emanuele6)