四、Shell运算
Bash shell 的算术运算有四种方式:
1. 使用 $(( )) 2. 使用$[ ] 3. 使用 expr 外部程式 4. 使用let 命令
注意:
n=1 let n+=1 等价于let n=n+1
1.整数值运算
使用expr命令:只能做整数运算,默认返回计算结果
格式:
expr 整数1 运算符 整数2 ...
整数值可以有变量提供,直接给出运算结果
+ 加法 expr 43 + 21 、expr $X + $Y - 减法 expr 43 - 21 、expr $X - $Y \* 乘法 expr 43 \* 21 、expr $X \* $Y / 除法 expr 43 / 21 、expr $X / $Y % 取余数 expr 43 % 21 、expr $X % $Y
例子:
#!/bin/bash #计算用户从终端输入的任意2个数的和 read -p "请输入第一个数" num1 read -p "请输入第二个数" num2 sum=`expr $num1 + $num2` echo "$num1 + $num2 = $sum"
使用$[]或$(())表达式
需借助echo输出结果,运算类型与expr类似 乘法*不用加转义符\ 使用变量时,直接指定变量名,不用加$符号
shell中如何进行算术运算:
let 算术运算表达式 let C=$A+$B $[算术运算表达式] C=$[$A+$B] $((算术运算表达式)) C=$(($A+$B)) expr 算术运算表达式,
表达式中各操作数及运算符之间要有空格,
而且要使用命令引用 C=`expr $A + $B`
2.表达式的简化
变量的递增、递减等操作
简写表达式 完整表达式 i++ i=i+1 i-- i=i-1 i*=2 i=i*2 i+=2 i=i+2 i-=2 i=i-2 i%=2 i=i%2
注意:
i++:先参与其他操作,后运算
++i:先运算,再参与其他操作
例子:
i=1 echo $((++i)) j=1 echo $((j++))
3.变量的自增/减等操作
使用let命令
操作变量值,只运算,不输出结果
若要查看结果,需借助echo命令
let:只做运算不返回计算结果,适用于自加和自减运算
#!/bin/bash i=10 let i-=2 echo $i let i-=2 echo $i echo ------------------- i=10 let i+=2 echo $i let i+=2 echo $i
变量的数值计算
变量的数值计算常用的有如下几个命令:
(())、let、expr、bc、$[]
1)(())用法:(此法很常用)
如果要执行简单的整数运算,只需将特定的算术表达式用”$((”和”))”括起来即可。
Shell的算术运算符号常置于”$((“......”))”的语法中。这一语法如同双引号的功能,除了内嵌双引号无需转义。
范例1:shell的运算实例如下:
[root@Web ~]# su - zgy [zgy@Web ~]$ ((a=1+2**3-4%3)) [zgy@Web ~]$ echo $a 8 [zgy@Web ~]$ b=$((1+2**3-4%3)) [zgy@Web ~]$ echo $b 8 [zgy@Web ~]$ echo $((a=1+2**3-4%3)) 8
提示:上面是三种不同的变量计算定义和使用的方式
[zgy@Web ~]$ echo $((a+=1)) #相当于a=a+1 9 [zgy@Web ~]$ echo $((a++)) 9 [zgy@Web ~]$ echo $((a--)) 10 [zgy@Web ~]$ echo $((3>2)) #比较大小 1 [zgy@Web ~]$ echo $((3<2)) 0 [zgy@Web ~]$ a=$((100*(100+1)/2)) [zgy@Web ~]$ echo $a 5050 [zgy@Web ~]$ echo $((100*(100+1)/2)) 5050
提示:
1.**为幂运算;%为取模运算(就是除法当中取余数)
2.上面涉及到的参数变量必须为整数(整型)。不能为小数(浮点数)或者字符串。后面的bc命令可以进行浮点数运算,但一般较少用到。
3.echo $((a++))和echo $((a--))表示先输出a自身的值,然后再进行++--的运算,echo $((++a))和echo $((--a))表示先进行++--的运算,再输出a自身的值
记忆方法:变量在前,先输出变量值,变量在后,就是先运算后输出变量的值。
范例2:--,++在变量前后的举例理解:
[root@Web ~]# a=10 [root@Web ~]# echo $((a++)) #先输出a的值,因为a为10,所以输出10 10 [root@Web ~]# echo $a #上面输出a的值后,a自增1,因此为11 11 [root@Web ~]# echo $((a++)) 11 [root@Web ~]# echo $a 12 [root@Web ~]# ((a++)) [root@Web ~]# echo $a 13 [root@Web ~]# a=10 [root@Web ~]# echo $((a--)) 10 [root@Web ~]# echo $a 9 [root@Web ~]# ((a--)) [root@Web ~]# echo $a 8 [root@Web ~]# echo $((++a)) 9 [root@Web ~]# echo $a 9 [root@Web ~]# echo $((++a)) 10 [root@Web ~]# echo $a 10 [root@Web ~]# echo $((++a)) 11 [root@Web ~]# echo $a 11 [root@Web ~]# echo $((--a)) 10 [root@Web ~]# echo $a 10 [root@Web ~]# echo $((--a)) 9 [root@Web ~]# echo $a 9
范例3:定义变量计算的例子:
[root@Web ~]# myvar=99 [root@Web ~]# echo $(($myvar + 1)) 100 [root@Web ~]# echo $(( $myvar + 1 )) #(())两边有几个空格不敏感,也可以没有 100 [root@Web ~]# myvar=$(( $myvar + 1 )) #还可以赋值给变量然后输出变量 [root@Web ~]# echo $myvar 100
范例4:各种(())的计算命令行执行例子:
[root@Web ~]# echo $((100/5)) #除法,取商 20 [root@Web ~]# echo $((100+5)) 105 [root@Web ~]# echo $((100*5)) 500 [root@Web ~]# echo $((100-5)) 95 [root@Web ~]# echo $((100**5)) #幂 10000000000 [root@Web ~]# echo $((100%5)) #取模,余数 0
范例5:各种(())运算的shell脚本例子
[root@localhost ~]# cat test.sh #!/bin/bash a=6 b=2 echo "a-b =$(($a-$b))" echo "a+b =$(($a+$b))" echo "a*b =$(($a*$b))" echo "a/b =$(($a/$b))" echo "a**b =$(($a**$b))" echo "a%b =$(($a%$b))"
执行结果如下:
[root@localhost ~]# sh test.sh a-b =4 a+b =8 a*b =12 a/b =3 a**b =36 a%b =0
范例6:这是一个实践考试题,内容如下:
请把a,b两个变量通过命令行传参的方式实现上面混合运算脚本的功能。
[root@localhost ~]# cat test1.sh #!/bin/bash a=$1 b=$2 echo "a-b =$(($a-$b))" echo "a+b =$(($a+$b))" echo "a*b =$(($a*$b))" echo "a/b =$(($a/$b))" echo "a**b =$(($a**$b))" echo "a%b =$(($a%$b))"
执行结果[root@localhost ~]# sh test1.sh 6 2
a-b =4 a+b =8 a*b =12 a/b =3 a**b =36 a%b =0
拓展:请实现一个加、减、乘、除等功能的计算器。通过命令行传参的方式实现上面脚本的功能。
答案:
[root@localhost ~]# cat d.sh #!/bin/bash echo$(($1)) [root@localhost ~]# cat j.sh #!/bin/bash echo $(($1$2$3)) [root@localhost ~]# sh j.sh 4+2 6 [root@localhost ~]# sh j.sh 4-2 2
学生例子:(如果敲不需要的内容会退出,待完善)
[root@localhost ~]# cat yubing_test.sh #!/bin/bash #add, subtract, multiply and divide by yubing print_usage(){ printf "Please enter an integer \n" exit 1 } read -p "Please input first number: " firstnum if [ -n "`echo $firstnum|sed 's/[0-9]//g' | sed 's/-//g'`" ];then print_usage fi read -p "Please input the operators: " operators if [ "${operators}" != "+" ]&&[ "${operators}" != "-" ] && [ "${operators}" != "*" ] && [ "${operators}" != "/" ];then echo "please use + - * /" exit 1 fi read -p "Please input second number: " secondnum if [ -n "`echo $secondnum|sed ' s/[0-9]//g' |sed ' s/-//g'`" ];then print_usage fi echo "${firstnum}${operators}${secondnum}=$((${firstnum}${operators}${secondnum}))"
执行结果:
[root@localhost ~]# sh yubing_test.sh Please input first number: 6 Please input the operators: + Please input second number: 2 6+2=8 [root@localhost ~]# sh yubing_test.sh Please input first number: 6 Please input the operators: * Please input second number: 2 6*2=12
作业:完成一个简单的四则运算计算器功能
(2)let命令的用法
格式:
let 赋值表达式
[注]let 赋值表达式功能等同于:((赋值表达式))
范例1:给自变量i加8
[root@localhost ~]# i=2 [root@localhost ~]# let i=i+8 [root@localhost ~]# echo $i 10 [root@localhost ~]# i=i+8 #去掉let定义 [root@localhost ~]# echo $i i+8
提示:let i=i+8等同于((i=i+8)),但后者效率更高
范例2:利用let计数监控web服务状态。
#!/bin/bash #监控服务状态 ServerMonitor(){ #服务状态监控 timeout=10 fails=0 success=0 while true do /usr/bin/wget --timeout=$timeout --tries-1 http://172.16.0.1/ -q -O /dev/null if [ $? -ne 0 ] then let fails=fails+1 success=0 else fails=0 let success=1 fi if [ $success -ge 1 ] then exit 0 fi if [$fails -ge 2 ];then Critical=" TMS 应用服务出现故障,请紧急处理!! " echo $Critical | mutt -s " 服务 down " www.magedu.com exit fi done }
(3)expr (evaluate expressions)命令的用法:
Expr命令一般用于整数值,但也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令行计算器
语法:expr Expression
[root@localhost ~]# expr 2 +2 expr: 语法错误 [root@localhost ~]# expr 2 + 2 4 [root@localhost ~]# expr 2 - 2 0 [root@localhost ~]# expr 2 * 2 expr: 语法错误 [root@localhost ~]# expr 2 \* 2 4 [root@localhost ~]# expr 2 / 2 1 [root@localhost ~]# expr 2 \*\* 2 expr: 语法错误 [root@localhost ~]# expr 3 % 2 1 [root@localhost ~]# expr 2+2 2+2
提示:
1、注意:运算符左右都有空格
2、使用乘号时,必须用反斜线屏蔽其特定含义。因为shell可能会误解星号的含义。
增量计数
Expr在循环中可用于增量计算。首先,循环初始化为0,然后循环值加1,反引号的用法为命令替换。最基本的一种是从(expr)命令接受输出并将之放入循环的变量。
例:给自变量i加1
[root@localhost ~]# i=0 [root@localhost ~]# i=`expr $i + 1` [root@localhost ~]# echo $i 1
expr $[$a+$b]表达式形式,其中$a$b可为整数值
[root@localhost ~]# expr $[2+3] 5 [root@localhost ~]# expr $[2*3] 6 [root@localhost ~]# expr $[2**3] 8 [root@localhost ~]# expr $[2/3] 0 [root@localhost ~]# expr $[2%3] 2 [root@localhost ~]# a=5 [root@localhost ~]# b=6 [root@localhost ~]# expr $[$a+$b] 11
expr将其后的串解释为表达式并计算其值,运算符前后须有空格
其它特殊的用法
expr用法ssh-copy-id
[root@localhost ~]# less /usr/bin/ssh-copy-id if expr "$1" : ".*\.pub" > /dev/null ; then
# expr : id_dsa.pub:’.*\.pub’,匹配*.pub格式的文件如果是则为真。例 [root@localhost ~]# expr "id_dsa.pub" : ".*\.pub" 10 #这里是匹配后字符数 #man expr STRING : REGEXP anchored pattern match of REGEXP in STRING
判断文件或字符串的扩展名小案例:
[root@localhost ~]# expr "test.pub" : ".*\.pub" && echo 1 || echo 0 8 1 [root@localhost ~]# expr "test.x" : ".*\.pub" && echo 1 || echo 0 0 0
技巧:通过expr判断变量是否为整数
[root@localhost ~]# cat judge_init.sh #!/bin/bash read -p "plus input:" a expr $a + 0 &>/dev/null [ $? -eq 0 ] && echo init || echo chars [root@localhost ~]# sh judge_init.sh plus input:q chars [root@localhost ~]# cat judge_init1.sh #!/bin/bash while true do read -p "plus input:" a expr $a + 0 &>/dev/null 2>&1 [ $? -eq 0 ] && echo init || echo chars Done [root@localhost ~]# sh judge_init1.sh plus input:123 init plus input:oldgirl chars plus input:123d chars plus input:q chars
通过expr 计算字符串的长度
[root@localhost ~]# chars=`seq -s" " 100` [root@localhost ~]# echo ${#chars} 291 [root@localhost ~]# echo $(expr length "$chars") 291
更多应用请man expr查看帮助
(4)bc命令的用法:
bc是UNIX下的计算器,它也可以用在命令行下面:
例:给自变量i加1
[root@localhost ~]# i=2 [root@localhost ~]# i=`echo $i+1|bc` #效率低 [root@localhost ~]# echo $i 3
因为bc支持科学计算,所以这种方法功能非常强大
[root@localhost ~]# echo 1+1 | bc 2 [root@localhost ~]# echo 3.5+5|bc 8.5 [root@localhost ~]# echo 3.5+5.6|bc 9.1 [root@localhost ~]# echo 3.5-3.1|bc .4 [root@localhost ~]# echo 3.5-2.1|bc 1.4 [root@localhost ~]# echo "5.23 * 3.13"|bc 16.36 [root@localhost ~]# echo "scale=1;5.23 * 3.13"|bc 16.36 [root@localhost ~]# echo "scale=1;5.23 / 3.13"|bc 1.6 [root@localhost ~]# echo "scale=6;5.23 * 3.13"|bc 16.3699 [root@localhost ~]# echo "scale=6;5.23 * 3.13"|bc -l 16.3699 [root@localhost ~]# echo "scale=3;5.23 / 3.13"|bc -l 1.670 [root@localhost ~]# echo "obase=2;8"|bc #10进制8转换成2进制 1000 [root@localhost ~]# echo "obase=16;20"|bc #10进制20转换成16进制 14
通过表达式计算
[root@localhost ~]# seq -s "+" 10 1+2+3+4+5+6+7+8+9+10 [root@localhost ~]# seq -s "+" 10|bc 55
特点:bc的特点是支持小数运算
(5)typeset命令的用法:
使用整数变量直接进行计算
例如:
[root@localhost ~]# typeset -i A=1 B=3 [root@localhost ~]# A=A+B [root@localhost ~]# echo $A 4
(5)$[]的用法:
实践操作演示:
[root@localhost ~]# echo $[ 2 + 3 ] 5 [root@localhost ~]# echo $[ 2 * 3 ] 6 [root@localhost ~]# echo $[2+ 3] 5 [root@localhost ~]# echo $[3-2] 1 [root@localhost ~]# echo $[3*2] 6 [root@localhost ~]# echo $[3/2] 1 [root@localhost ~]# echo $[3**2] 9 [root@localhost ~]# echo $[3%2] 1