21

In shell script we can substitute expr $a*$b with $(($a+$b)).

But why not just with (($a+$b)), because in any resource it is written that (()) is for integer computation.

So we use $(()) when there are variables instead of integer values do we? And what should we use instead of $(()) when variables can receive float values?

1

3 Answers 3

36
  1. For arithmetic, expr is archaic. Don't use it.*

  2. $((...)) and ((...)) are very similar. Both do only integer calculations. The difference is that $((...)) returns the result of the calculation and ((...)) does not. Thus $((...)) is useful in echo statements:

     $ a=2; b=3; echo "$((a*b))" 6 

    ((...)) is useful when you want to assign a variable or set an exit code:

     $ a=3; b=3; ((a==b)) && echo yes yes 
  3. If you want floating point calculations, use bc or awk:

    $ echo '4.7/3.14' | bc -l 1.49681528662420382165 $ awk 'BEGIN{print 4.7/3.14}' 1.49682 

*As an aside, expr remains useful for string handling when globs are not good enough and a POSIX method is needed to handle regular expressions.

6
  • 1
    If expr is archaic what should we use instead of expr text : '.*'
    – Stranger
    CommentedMay 29, 2016 at 8:44
  • If s is a shell variable, its length is ${#s}
    – John1024
    CommentedMay 29, 2016 at 8:53
  • ${#} means a number of arguments and $(#s} means a number of characters of a variable does it?
    – Stranger
    CommentedMay 29, 2016 at 9:02
  • Yes. That's right.
    – John1024
    CommentedMay 29, 2016 at 10:21
  • 5
    @Stranger Many uses of expr STRING : REGEX can be written as case STRING in PATTERN). expr is only useful when REGEX can't be expressed with shell wildcards.CommentedMay 29, 2016 at 23:10
2

expr is old, but it does have one limited use I can think of. Say you want to search a string. If you want to stay POSIX with grep, you need to use a pipe:

if echo november | grep nov then : do something fi 

expr can do this without a pipe:

if expr november : nov then : do something fi 

the only catch is expr works with anchored strings, so if you want to match after the beginning you need to change the REGEXP:

if expr november : '.*ber' then : do something fi 

Regarding (( )), this construct is not POSIX, so should be avoided.

Regarding $(( )), you do not have to include the dollar sign:

$ fo=1 $ go=2 $ echo "$((fo + go))" 3 
1
  • 4
    Many uses of expr STRING : REGEX can be written as case STRING in PATTERN). expr is only useful when REGEX can't be expressed with shell wildcards.CommentedMay 29, 2016 at 23:08
2

It seems that the following programs do more or less the same and they don't really differ. But that is not true.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )); do s=$((s+1)) done echo "$s" 

This is the correct way to implement this. The expression s+1 is evaluated by the shell and can be assigned to a variable.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )); do s=`expr "$s" + 1` done echo "$s" 

Here the expression will be calculated by the program expr, which isn't a shell builtin but an external Unix program. So instead of simply adding 1 and s a program must be started und its output must be read and written to the variable. Starting a programm needs a lot of resources and a lot of time. And this program is run 1000000 times. So the program will be much slower than the previous. Nevertheless the code works correctly.

#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )); do ((s=s+1)) done echo "$s" 

If the -e flag isn't set, the program will work correctly, too. But if -e is set when s=-1 and ((s=s+1)) is calculated. The expression s=s+1 evaluates to 0 and the exit code of ((0)) is >0 which is interpreted as an error by the shell and the shell exits the program.

The reason to set the -e flag is that it is the simplest way of error processing: stop if an error ocurrs.

1
  • 1
    While the points about invoking external programs and the -e flag were correct, the code needed fixing. I edited the post: the for loops needed closing with a 'done', and the arguments of expr needed separating with spaces.
    – johnraff
    CommentedMar 28, 2023 at 2:52

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.