grok12
grok12

Reputation: 3676

Are these bash statements all equivalent?

I just discovered this great site. I was reading bash tagged posts when the following question entered my mind:

This code:

var=$RANDOM

var1=$[ $var % 13 ]
echo "var1 = $var1"

var2=$( $var % 13 )
echo "var2 = $var2"

var3=$(( $var % 13 ))
echo "var3 = $var3"

var4=`expr $var % 13` # Note revised from original post by adding the expr
echo "var4 = $var4"

Produces this output:

var1 = 7
./question: line 7: 23225: command not found
var2 = 
var3 = 7
var4 = 7

So only the var2 statement does not work. My question is: is it only a matter of personal choice as to which of the other three should be used or are there other considerations that should be taken into account?

(I've edited this question extensively after seeing replies. Hope I'm doing this the right way.)

Upvotes: 3

Views: 151

Answers (4)

Gordon Davisson
Gordon Davisson

Reputation: 126038

The $[] and $(()) versions are essentially interchangeable, except that not all shells support $[], so don't use it -- use $(()) instead. Also, in both of these forms, variables used in the expression will be automatically expanded, so you don't need to use $ inside them:

var=$RANDOM
echo $var             # prints 7482 (in my example run)
echo $[ $var % 13 ]   # prints 7
echo $[ var % 13 ]    # prints 7
echo $(( $var % 13 )) # prints 7
echo $(( var % 13 ))  # prints 7

expr is actually a command which does expression evaluation -- it has most of the same capabilities as the builtin expression evaluation, but without some of the niceties. For instance, you must use $ to expand variables, and must escape any operators that the shell would treat as special characters (e.g. <, >, |, etc):

expr $var % 13        # prints 7
echo `expr $var % 13` # prints 7, just by a less direct route

$() is totally different -- it doesn't do arithmetic evaluation, it runs its contents as a command. In fact, it's almost the same as backquotes (except that it is easier to read, and has much cleaner syntax, so I always use it instead of backquotes):

echo $(expr $var % 13) # prints 7, same as with backquotes

And just to make this more complicated, let me add some more options:

(( var5 = var % 13 )) # This is an arithmetic statement (that happens to contain an assignment)
echo $var5            # prints 7
let "var6 = var % 13" # Another form for pretty much the same thing
echo $var6            # prints 7

declare -i var7  # declare var7 as an integer...
var7="var % 13"  #  to force values assigned to it to be evaluated
echo $var7       # prints 7

So what should you use? I'd go with var3=$(( var % 13 )) for maximum compatibility and (IMHO) clean syntax.

Upvotes: 4

user unknown
user unknown

Reputation: 36259

((var%=13))

is another way, a shortcut for var=((var%13))

Upvotes: 1

The $[…] and $((…)) are exactly equivalent. However, the $[…] form is a deprecated bash and zsh extension; the $((…)) form is standard.

The expr form is roughly equivalent, but it calls the external program expr. In the old days, shells didn't have many built-in capabilities, in particular no arithmetic, and so one would use expr for arithmetic. Nowadays there's not much use for expr.

$( $var % 13 ) is just broken, it tries to call $var (or more precisely, the first word of it) as a command name.

Upvotes: 2

anubhava
anubhava

Reputation: 786011

Invalid command

var=$( $var % 13 )

Valid command but prefer $(( var % 13 ))

var=$(( $var % 13 ))

Invalid command

var=$var % 13

Outcome: So out of all only $(( var % 13 )) is the valid way to get the modulo of $var by 13.

Update

After your edits I would say use either var1 or var3 way of getting modulo calculated. expr is an external program and its better to use bash's internal utility to get the same job done.

Upvotes: 1

Related Questions