算术运算
Bash的算术运算有以下几种方法
算术扩展 $((算术式)) r=$((2+5*8))
使用外部程序expr expr算术式 r=`expr 4 + 5`
使用$[] $[算术式] r=$[4+5]
使用内置命令declare declare -i 变量=算术式 declare -i r=8+16
使用内置命令let let算术式 let r=8+16
上述的算术式可以包含变量、变量扩展,在进行计算之前,变量会被替换,扩展式会先展开。
echo $((${j:-8}+2)) 如果变量j不存在或空值,则${j:-8}展示的结果为8,再和2做加法运算,得值为10。
echo $((k+4)) 如果变量k不存在或空值,则值为0+4=4
echo $(($k+4)) 如果变量k不存在或为空值,语法错误.
如果数字以0开头,则视为八进制数字 如016等于十进制的14(1*8+6=14)
如果数字以0x或0X开头,视为16进制数字
不同进制的数字,可使用"基底#数字"的表示法,其中基底范围为2~64。如果数字超过9,则以a代表10,b代表11,其他依此类推 例:十五进制数15#1b,其值为1*15+11=26
运算符的优先级之分,详见<<实战LINUX SHELL编程与服务器管理>>的P168页,对应PDF的184页。
r=$((6/5)) //无条件舍弃余数,值为1
r=$((2**5)) //计算2的5次方,r的值为32
r=$((32%3)) //r的值为2
r=6 r=$((++r))
m=16 r=$((m<<1)) //左移一位,值*2,输出32
m=16 r=$((m>>1)) //右移一位, 值/2,输出8
m=10 r=$((m|3)) //或运算
m=10 r=$((m$3)) //与运算
((i=168)) //指定运算,设定变量i的值为168
i=168 ((i++))
i=168 ((i/=2))
i=168 ((n=i<100?50:80))
范例1:
下列范例是由命令行读取一个整数值,将它转成二进制数,并计算位是1的个数,然后显示出来。
#!/bin/sh
declare -i a i q s=0 //宣告a、i、q、s为数值型,s初始值为0
a=${1:-255} //a设为命令行取得的参数值$1,如果没有提供,则a的默认值为255。关于这个用法,见7.1节
mask="128 64 32 16 8 4 2 1"
Bmap=
echo "1的位数 128 64 32 16 8 4 2 1"
for i in $mask
do
q=$((a/i))
((s+=q))
[ $q -gt 0 ] && Bmap=$Bmap"__1__" || Bmap=$Bmap"__0__" //q>0则执行Bmap=$Bmap"__1__",否则执行Bmap=$Bmap"__0__"
a=$((a-q*i))
done
echo " $s : $Bmap"
使用外部程序expr做算术运算
外部程序expr本来的作用,是在"标准输出"显示表示式的值。expr是外部程序,和shell的版本没什么关系,几乎在各种操作系统平台上都可以执行。因此,如果注重跨平台、可移植性,在script程序的开发上可使用expr替代其他算术运算方法。
在使用expr时,要特别注意“表示式”中是否含有bash shell的特殊字符,如*、|、<、>、&、(、)等。如果有的话,需要用\予以转义,否则会出现奇怪的错误信息。其次,在“表达式”中,运算符和操作数之间,至少要有一个以上的空格符隔开。
r=`expr 参数1 \| 参数2`
|代表"或"之意。如果"参数1"存在、非空、不是0,则传回“参数1”的值,否则,传回“参数2”的值。由于|是特殊字符,所以要写成转义字符\|。
r=`expr 3 \| 0` //r=3
r=`expr 0 \| 2` //r=2
r=`expr 0 \| 0` //r=0
r=`expr 参数1 \& 参数2`
如果“参数1”和“参数2”皆存在、非空、不是0,则传回“参数1”的值,否则传回0。
expr其它的详细用法用<<shell编程与服务器管理>>P177页,或PDF P193页.
declare和let的用法详见<<shell编程与服务器管理>>