Doing Arithmetic in Your Shell Script

Problem

You need to do some simple arithmetic in your shell script.

Solution

Use $(( )) or let for integer arithmetic expressions.

COUNT=$((COUNT + 5 + MAX * 2))
let COUNT+=5+MAX*2

Discussion

As long as you keep to integer arithmetic, you can use all the standard (i.e., C-like) operators inside of $(()) for arithmetic. There is one additional operator—you can use ** for raising to a power, as in MAX=$((2**8)), which yields 256.

Spaces are not needed nor are they prohibited around operators and arguments (though ** must be together) within a $(( )) expression. But you must not have spaces around the equals sign, as with any bash variable assignment. If you wrote:

COUNT = $((COUNT + 5)) # not what you think!

then bash will try to run a program named COUNT and its first argument would be an equal sign, and its second argument would be the number you get adding 5 to the value of $COUNT. Remember not to put spaces around the equal sign.

Another oddity to these expressions is that the $ that we normally put in front of a shell variable to say we want its value (as in $COUNT or $MAX ) is not needed inside the double parentheses. For example, $((COUNT +5 MAX * 2)) needs no dollar sign on the shell variables—in effect, the outer $ applies to the entire expression.

We do need the dollar sign, though, if we are using a positional parameter (e.g.,$2) to distinguish it from a numeric constant (e.g., “2”). Here’s an example:

COUNT=$((COUNT + $2 + OFFSET))

There is a similar mechanism for integer arithmetic with shell variables using the bash built-in let statement. It uses the same arithmetic operators as the $(()) construct:

let COUNT=COUNT+5

When using let, there are some fancy assignment operators we can use such as this (which will accomplish the same thing as the previous line):

let COUNT+=5

(This should look familiar to programmers of C/C++ and Java.)

Table 6-1 shows a list of those special assignment operators.

Table 6-1. Explanation of assignment operators in bash

Operator

Operation with assignment

Use

Meaning

=

Simple assignment

a=b

a=b

*=

Multiplication

a*=b

a=(a*b)

/=

Division

a/=b

a=(a/b)

%=

Remainder

a%=b

a=(a%b)

+=

Addition

a+=b

a=(a+b)

-=

Subtraction

a-=b

a=(a-b)

<<=

Bit-shift left

a<<=b

a=(a<<b)

>>=

Bit-shift right

a>>=b

a=(a>>b)

&=

Bitwise “and”

a&=b

a=(a&b)

^=

Bitwise “exclusive or”

a^=b

a=(a^b)

|=

Bitwise “or”

a|=b

a=(a|b)

These assignment operators are also available with $(( )) provided they occur inside the double parentheses. The outermost assignment is still just plain old shell variable assignment.

The assignments can also be cascaded, through the use of the comma operator:

echo $(( X+=5 , Y*=3 ))

which will do both assignments and then echo the result of the second expression (since the comma operator returns the value of its second expression). If you don’t want to echo the result, the more common usage would be with the let statement:

let   X+=5 Y*=3

The comma operator is not needed here, as each word of a let statement is its own arithmetic expression.

Unlike many other places in bash scripts where certain characters have special meanings (like the asterisk for wildcard patterns or parentheses for subshell execution), in these expressions we don’t need to use quotes or backslashes to escape them since they don’t have their special meaning in let statements or inside of the $(( )) construct:

let Y=(X+2)*10

Y=$(( ( X + 2 ) * 10 ))

One other important difference between the let statement and the $(( )) syntax deals with the rather minor issue of the whitespace (i.e., the space character). The let statement requires that there be no spaces around not only the assignment operator (the equal sign), but around any of the other operators as well; it must all be packed together into a single word.

The $(( )) syntax, however, Can be much more generous, allowing all sorts of whitespace within the parentheses. For that reason, it is both less prone to errors and makes the code much more readable and is, therefore, our preferred way of doing bash integer arithmetic. However, an exception can be made for the occasional += assignment or ++ operator, or when we get nostalgic for the early days of BASIC programming (which had a LET statement).

Warning

Remember; this is integer arithmetic, not floating point. Don’t expect much out of an expression like 2/3, which in integer arithmetic evaluates to 0 (zero). The division is integer division, which will truncate any fractional result.

See Also

  • help let

  • bash manpage

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.76.175