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.)
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.
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.
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.
((var%=13))
is another way, a shortcut for var=((var%13))
精彩评论