Differences between revisions 3 and 4
Revision 3 as of 2009-12-30 17:18:08
Size: 1544
Editor: MatthiasPopp
Comment:
Revision 4 as of 2010-04-07 18:10:25
Size: 1688
Editor: GreyCat
Comment: remove non-POSIX-safe use of -a/-o
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:
== How can I group expressions, e.g. (A AND B) OR C? ==
The TestCommand {{{[}}} uses parentheses () for expression grouping. Given that "AND" is "-a", and "OR" is "-o", the following expression
== 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:
Line 6: Line 6:
    (0<n AND n<=10) OR n=-1     # Bourne
    if test A && test B || test C; then
    ...
Line 9: Line 11:
can be written as follows: The grouping is implicit in this case, because AND (`&&`) has a higher precedence than OR (`||`). If we need explicit grouping, then we can use curly braces:
Line 12: Line 14:
    if [ \( $n -gt 0 -a $n -le 10 \) -o $n -eq -1 ]
    then
        echo "0 < $n <= 10, or $n=-1"
    else
        echo "invalid number: $n"
    fi
    # Bourne(?)
    if test A && { test B || test C; }; then
    ...
Line 20: Line 19:
Note that the parentheses have to be quoted: \(, '(' or "(". What we should ''not'' do is try to use the `-a` or `-o` operators of the `test` command, because the results are undefined.
Line 28: Line 27:
    # Bash/ksh
Line 35: Line 35:
    # Bash/ksh

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:

    # Bourne
    if test A && test B || test C; then
    ...

The grouping is implicit in this case, because AND (&&) has a higher precedence than OR (||). If we need explicit grouping, then we can use curly braces:

    # Bourne(?)
    if test A && { test B || test C; }; then
    ...

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

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

Examples:

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

or

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

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

    n=3
    if [[ n>0 && n<10 ]]
    then echo "$n is between 0 and 10"
    else echo "ERROR: invalid number: $n"
    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)