3.6. Operations and Related Topics

3.6.1. Operators

assignment

=

All-purpose assignment operator, which works for both arithmetic and string assignments.

   1 var=27
   2 category=minerals  # No spaces allowed after the "=".

Caution

Do not confuse the "=" assignment operator with the = test operator.

   1 #    = as a test operator
   2 
   3 if [ "$string1" = "$string2" ]
   4 # if [ "Xstring1" = "Xstring2" ] is safer,
   5 # to prevent an error message should one of the variables be empty.
   6 # (The prepended "X" characters cancel out.) 
   7 then
   8    command
   9 fi

arithmetic operators

+

plus

-

minus

*

multiplication

/

division

%

modulo, or mod (returns the remainder of an integer division operation)

 bash$ echo `expr 5 % 3`
 2
 	      

This operator finds use in, among other things, generating numbers within a specific range (see Example 3-39 and Example 3-40) and formatting program output (see Example 3-154). It can even be used to generate prime numbers, (see Example A-10).

+=

"plus-equal" (increment variable by a constant)

let "var += 5" results in var being incremented by 5.

-=

"minus-equal" (decrement variable by a constant)

*=

"times-equal" (multiply variable by a constant)

let "var *= 4" results in var being multiplied by 4.

/=

"slash-equal" (divide variable by a constant)

%=

"mod-equal" (remainder of dividing variable by a constant)

Arithmetic operators often occur in an expr or let expression.


Example 3-20. Using Arithmetic Operations

   1 #!/bin/bash
   2 # Counting to 6 in 5 different ways.
   3 
   4 n=1; echo -n "$n "
   5 
   6 let "n = $n + 1"   # let "n = n + 1"   also works.
   7 echo -n "$n "
   8 
   9 : $((n = $n + 1))
  10 # ":" necessary because otherwise Bash attempts
  11 # to interpret "$((n = $n + 1))" as a command.
  12 echo -n "$n "
  13 
  14 n=$(($n + 1))
  15 echo -n "$n "
  16 
  17 : $[ n = $n + 1 ]
  18 # ":" necessary because otherwise Bash attempts
  19 # to interpret "$((n = $n + 1))" as a command.
  20 # Works even if "n" was initialized as a string.
  21 echo -n "$n "
  22 
  23 n=$[ $n + 1 ]
  24 # Works even if "n" was initialized as a string.
  25 # Avoid this type of construct, since it is obsolete and nonportable.
  26 echo -n "$n "; echo
  27 
  28 # Thanks, Stephane Chazelas.
  29 
  30 exit 0

Caution

Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.

   1 a=1.5
   2 
   3 let "b = $a + 1.3"  # Error.
   4 # t2.sh: let: b = 1.5 + 1.3: syntax error in expression (error token is ".5 + 1.3")
   5 
   6 echo "b = $b"       # b=1
Use bc in scripts that that need floating point calculations or math library functions.

bitwise operators. The bitwise operators seldom make an appearance in shell scripts. Their chief use seems to be manipulating and testing values read from ports or sockets. "Bit flipping" is more relevant to compiled languages, such as C and C++, which run fast enough to permit its use on the fly.

<<

bitwise left shift (multiplies by 2 for each shift position)

<<=

"left-shift-equal"

let "var <<= 2" results in var left-shifted 2 bits (multiplied by 4)

>>

bitwise right shift (divides by 2 for each shift position)

>>=

"right-shift-equal" (inverse of <<=)

&

bitwise and

&=

"bitwise and-equal"

|

bitwise OR

|=

"bitwise OR-equal"

~

bitwise negate

!

bitwise NOT

^

bitwise XOR

^=

"bitwise XOR-equal"

relational tests

<

less than

>

greater than

<=

less than or equal to

>=

greater than or equal to

==

equal to (test)

!=

not equal to

logical operators

&&

and (logical)

   1 if [ $condition1 ] && [ $condition2 ]
   2 # Same as:  if [ condition1 -a condition2 ]
   3 # Returns true if both condition1 and condition2 hold true...

Note

&& may also, depending on context, be used in an and list to concatenate commands.

||

or (logical)

   1 if [ $condition1 ] || [ $condition2 ]
   2 # Same as:  if [ condition1 -o condition2 ]
   3 # Returns true if either condition1 or condition2 holds true...

Note

Bash tests the exit status of each statement linked with a logical operator.


Example 3-21. Compound Condition Tests Using && and ||

   1 #!/bin/bash
   2 
   3 a=24
   4 b=47
   5 
   6 if [ "$a" -eq 24 ] && [ "$b" -eq 47 ]
   7 then
   8   echo "Test #1 succeeds."
   9 else
  10   echo "Test #1 fails."
  11 fi
  12 
  13 # ERROR:   if [ "$a" -eq 24 && "$b" -eq 47 ]
  14 #          attempts to execute  ' [ "$a" -eq 24 '
  15 #          and fails to finding matching ']'.
  16 #
  17 #    if [[ $a -eq 24 && $b -eq 24 ]]   works
  18 #    (The "&&" has a different meaning in line 17 than in line 6.)
  19 #    Thanks, Stephane Chazelas.
  20 
  21 
  22 if [ "$a" -eq 98 ] || [ "$b" -eq 47 ]
  23 then
  24   echo "Test #2 succeeds."
  25 else
  26   echo "Test #2 fails."
  27 fi
  28 
  29 
  30 # The -a and -o options provide
  31 # an alternative compound condition test.
  32 # Thanks to Patrick Callahan for pointing this out.
  33 
  34 
  35 if [ "$a" -eq 24 -a "$b" -eq 47 ]
  36 then
  37   echo "Test #3 succeeds."
  38 else
  39   echo "Test #3 fails."
  40 fi
  41 
  42 
  43 if [ "$a" -eq 98 -o "$b" -eq 47 ]
  44 then
  45   echo "Test #4 succeeds."
  46 else
  47   echo "Test #4 fails."
  48 fi
  49 
  50 
  51 a=rhino
  52 b=crocodile
  53 if [ "$a" = rhino ] && [ "$b" = crocodile ]
  54 then
  55   echo "Test #5 succeeds."
  56 else
  57   echo "Test #5 fails."
  58 fi
  59 
  60 exit 0

The && and || operators also find use in an arithmetic context.

 bash$ echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0))
 1 0 1 0
 	      

3.6.2. Numerical Constants

A shell script interprets a number as decimal (base 10), unless that number has a special prefix or notation. A number preceded by a 0 is octal (base 8). A number preceded by 0x is hexadecimal (base 16). A number with an embedded # is evaluated as BASE#NUMBER (this option is of limited usefulness because of range restrictions).


Example 3-22. Representation of numerical constants:

   1 #!/bin/bash
   2 
   3 # Representation of numbers.
   4 
   5 # Decimal
   6 let "d = 32"
   7 echo "d = $d"
   8 # Nothing out of the ordinary here.
   9 
  10 
  11 # Octal: numbers preceded by '0'
  12 let "o = 071"
  13 echo "o = $o"
  14 # Expresses result in decimal.
  15 
  16 # Hexadecimal: numbers preceded by '0x' or '0X'
  17 let "h = 0x7a"
  18 echo "h = $h"
  19 
  20 # Other bases: BASE#NUMBER
  21 # BASE between 2 and 36.
  22 let "b = 32#77"
  23 echo "b = $b"
  24 # This notation only works for a limited range of numbers (2 - 36)
  25 # ... 10 digits + 26 alpha characters = 36.
  26 let "c = 2#47"  # Error: out of range.
  27 echo "c = $c"
  28 
  29 echo $((36#zz)) $((2#10101010)) $((16#AF16))
  30 
  31 
  32 # Thanks, S.C., for clarification.
  33 
  34 exit 0