shell编程:变量的数值计算实践(五)
算术运算符

变量的数值(整数)计算
1)(())用法:(此方法很常用)**

范例:shell的算术运算实例如下:
|
1
2
3
4
5
6
7
8
|
[root@db01 ~]# ((a=1+2**3-4%3))[root@db01 ~]# echo $a8[root@db01 ~]# ((a=1+2**3-4%3))[root@db01 ~]# echo $a8[root@db01 ~]# echo $((1+2**3-4%3))8 |
记忆方法:++,--
变量a在前,表达式的值为a,然后a自增或自减,变量a在符号后,表达式值自增或自减,然后a值自增或自减
|
1
2
3
|
[root@db01 ~]# a=$((100*(100+1)/2))[root@db01 ~]# echo $a5050 |
范例6:这是一个实践考试题,内容如下:
把a,b两个变量通过命令行脚本传参的方式实现上面混合运算脚本的功能
第一种方法:
|
1
2
3
4
5
6
7
8
9
|
#!/bin/basha=6b=2echo "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 ))" |
第二种方法:
|
1
2
3
4
5
6
7
8
9
10
|
[root@web02 ~]# cat abc.sh#!/bin/basha=$1b=$2echo "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 ))" |
2)let命令的用法(整数)
格式: let 赋值表达式
【注】let赋值表达式功能等同于:((赋值表达式))
范例1:给自变量i加8
|
1
2
3
4
|
[root@db01 scripts]# i=2[root@db01 scripts]# let i=i+8[root@db01 scripts]# echo $i10 |
范例2:监控web服务状态,如果访问两次均失败,则报警(let应用案例)
[root@adminset 05]# cat checkurl.sh
#!/bin/bash
CheckUrl() {
timeout=5
fails=0
success=0
while true
do
wget --timeout=$timeout --tries=1 http://www.baidu.com -q -o /dev/null
if [ $? -ne 0 ]
then
let fails=fails+1
else
let success+=1
fi
if [ $success -ge 1 ]
then
echo sunccess
exit 0
fi
if [ $fails -ge 2 ]
then
Critical="sys is down"
echo $Critical|tee|mail -s "$Critical" 249495480@qq.com
exit 2
fi
done
}
CheckUrl
运行结果:
[root@adminset 05]# sh checkurl.sh sunccess [root@adminset 05]# sh +x checkurl.sh sunccess [root@adminset 05]# sh -x checkurl.sh + CheckUrl + timeout=5 + fails=0 + success=0 + true + wget --timeout=5 --tries=1 http://www.baidu.com -q -o /dev/null + '[' 0 -ne 0 ']' + let success+=1 + '[' 1 -ge 1 ']' + echo sunccess sunccess + exit 0
3)expr (evaluate(求值)expressions(表达式))命令的用法:
expr命令一般用于整数值,但也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令计算器
范例:命令运算用法实践
[root@adminset 05]# expr 2+2 2+2 [root@adminset 05]# expr 2 + 2 4 [root@adminset 05]# expr 2 - 2 0 [root@adminset 05]# expr 2 * 2 expr: syntax error [root@adminset 05]# expr 2 \* 2 4 [root@adminset 05]# expr 2 / 2 1
要注意,在使用expr时:
- 运算符及用于计算的数字左右都至少有一个空格,否则会报错
- 使用称号时:必须用反斜线屏蔽其特定含义,因为Shell可能会误解星号的含义
范例:给自变量i加6
[root@adminset 05]# i=5 [root@adminset 05]# i=`expr $i + 6` #注意用反引号将表达式引起来,变量和数字符号两边有空格 [root@adminset 05]# echo $i 11
范例:通过传参判断输出内容是否为整数
#!/bin/sh expr $1 + 1>/dev/null 2>&1 [ $? -eq 0 ]&&echo int||echo chars #这是一个条件表达式语法,返回值为0,则输出int,否则输出chars
范例:通过read读入持续等待输入例子(此为范例5-16的加强版)
#!/bin/sh while true do read -p "pls input:" a expr $a + 0 >/dev/null 2>&1 [ $? -eq 0 ] && ehco int || echo chars done
四种运算方法:
1.(())
2.let
3.expr
4.[]
整数
判断一个文件的扩展名是不是pub(发送公钥的命令就是使用此参数)
|
1
2
3
4
5
6
7
8
9
10
11
|
#!/bin/shif expr "$1" : ".*\.pub" &>/dev/nullthenecho "you are using $1"elseecho "pls use *.pub file"fi[root@web02 ~]# sh aaa.sh oldboypls use *.pub file[root@web02 ~]# sh aaa.sh oldboy.pubyou are using oldboy.pub |
判断一个输入是不是数字
|
1
2
3
4
5
6
7
|
#!/bin/shwhile truedoread -p "Pls input:" aexpr $a + 0 >/dev/null 2>&1[ $? -eq 0 ] &&echo int||echo charsdone |
如果判断是不是数字,就执行错误shars
|
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@db01 scripts]# cat b.sh#!/bin/shexpr $1 + 1 >/dev/null 2>&1[ $? -eq 0 ] &&echo int||echo chars[root@db01 scripts]# sh b.sh 1int[root@db01 scripts]# sh b.sh 1achars[root@db01 scripts]# sh b.sh 100int[root@db01 scripts]# sh b.sh 100abcchars |
expr match 整数判断
|
1
2
3
4
|
[[ `expr match "$a" "[0-9][0-9]*$"` == 0 ]] && {echo "the first is not a num"exit 3} |
计算变量长度
|
1
2
3
|
[root@db01 scripts]# a="oldboy"[root@db01 scripts]# expr length "$a"6 |
expr功能
1.整数计算
2.判断扩展名
3.判断输入是否为整数
4.计算变量的长度
bc命令用法
|
1
2
3
4
5
6
7
8
9
10
11
|
[root@db01 scripts]# bcbc 1.06.95Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.This is free software with ABSOLUTELY NO WARRANTY.For details type `warranty'.1+121+346*848 |
另一种使用bc的方式
|
1
2
3
4
|
[root@db01 scripts]# echo 1+2|bc3[root@db01 scripts]# echo 8-2|bc6 |
inux下的bc命令可以设置结果的位数,通过scale.
|
1
2
3
4
5
6
7
|
[root@db01 scripts]# echo "scale=3;5.23 / 3.13"|bc1.670[root@db01 scripts]# echo "scale=2;5.23 / 3.13"|bc1.67比如:$ echo "scale=4; 1.2323293128 / 1.1" | bc -l1.1202 |
bc命令简单的计算
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[root@web02 ~]# i=2[root@web02 ~]# i=`echo $i+1|bc`[root@web02 ~]# echo $i3可以做加法计算[root@web02 ~]# echo 3.5+53.5+5[root@web02 ~]# echo 3.5+5|bc8.5减法计算[root@web02 ~]# echo 3.5-5|bc-1.5乘法计算[root@web02 ~]# echo 3.5*5|bc17.5保留位数(bc的用处不大)[root@web02 ~]# echo "scale=2; 3.5*5.1"|bc17.85[root@web02 ~]# echo "scale=2; 3*5"|bc15[root@web02 ~]# echo "scale=1; 3*5"|bc15提示:bc是特有的小数计算awk也可以进行小数计算[root@web02 ~]# echo "5.5 5.6" |awk '{print ($2-$1)}'0.1[root@web02 ~]# echo "5.5 5.5" |awk '{print ($2+$1)}'11 |
利用bc配合变量运算
|
1
2
3
4
|
[root@adminset 05]# i=5[root@adminset 05]# i=`echo $i+6|bc` #利用echo输出表达式,通过管道交给bc计算,此方法效率较低[root@adminset 05]# echo $i11 |
提示:根据bc所具有的特殊性来看:
- 如果小数,则选择bc运算没有问题(老男孩推荐awk)
- 若是整数场景,可用(())、let、expr等
范例:通过一条命令计算输出1+2+3+...+10的表达式,并计算出结果,使用bc计算
输出内容如:1+2+3+4+5+6+7+8+9+10=55
第一种方法:
|
1
2
3
4
|
[root@web02 ~]# seq -s "+" " "101+2+3+4+5+6+7+8+9+10[root@web02 ~]# echo `seq -s "+" " "10`=`seq -s "+" " "10|bc`1+2+3+4+5+6+7+8+9+10=55 |
第二种方法:
|
1
2
3
4
|
[root@web02 ~]# echo {1..10}|tr " " "+"1+2+3+4+5+6+7+8+9+10[root@web02 ~]# echo `echo {1..10}|tr " " "+"`=`echo {1..10}|tr " " "+"|bc`1+2+3+4+5+6+7+8+9+10=55 |
更多方法:因计算不是重点,所以我们不重点研究。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@adminset 05]# echo `seq -s "+" 10`="$((`seq -s "+" 10`))"1+2+3+4+5+6+7+8+9+10=55#使用(())计算[root@adminset 05]# echo `seq -s "+" 10`=`seq -s "+" 10|bc`1+2+3+4+5+6+7+8+9+10=55#使用bc计算[root@adminset 05]# echo `seq -s "+" 10`=`seq -s " + " 10|xargs expr`1+2+3+4+5+6+7+8+9+10=55#使用expr计算[root@adminset 05]# echo `seq -s "+" 10`=$(echo $[`seq -s " + " 10`])1+2+3+4+5+6+7+8+9+10=55#使用$[]计算 |
特点:bc的独有特点是支持小数运算,当然也可以整数运算。
AWK实现计算
利用awk进行运算的效果也很好,适合小数和证书,特别是命令行计算,尤其是小数,运算很精确,好用
[root@adminset 05]# echo "7.7 3.8"|awk '{print ($1-3)/$2}'
1.23684
#$1为第一个数字,$1为第二个数字,用空格隔开,下同
[root@adminset 05]# echo "7.7 3.8"|awk '{print ($1-$2)/$2}'
1.02632
[root@adminset 05]# echo "7.7 3.8"|awk '{print ($1-$2)}'
3.9
[root@adminset 05]# echo "358 113"|awk '{print ($1-3)/$2}'
3.14159
[root@adminset 05]# echo "3 9"|awk '{print ($1-3)*$2}'
0
[root@adminset 05]# echo "3 9"|awk '{print ($1+3)*$2}'
54
declare(同typeset)命令的用法
下面将要讲解的是使用typeset定义整数变量,直接进行计算,这个方法不是很常用,因为需要定义才能生效,示例如下:
[root@adminset 05]# [root@adminset 05]# declare -i A=30 B=7 #declare -i参数可以将变量定义为整形 [root@adminset 05]# A=A=B #因为已声明是整型,因此可以直接进行运算了 [root@adminset 05]# echo $A 7 [root@adminset 05]# A=A+B [root@adminset 05]# echo $A 14
$[]符号的运算示例
[root@adminset 05]# [root@adminset 05]# i=5 [root@adminset 05]# i=$[i+6] [root@adminset 05]# echo $i 11 [root@adminset 05]# echo $[2*3] 6 [root@adminset 05]# echo $[2**3] 8 [root@adminset 05]# echo $[2/5] 0 [root@adminset 05]# echo $[3/2] 1 [root@adminset 05]# echo $[3%2] 1 [root@adminset 05]# echo $[3 % 2] 1
下面是一个解决实际问题的示例:打印数学杨辉三角
#!/bin/bash
if (test -z $1);then #判断传参的值长度是不是为0,如果没有传入参数,则使用read读入
read -p "input MAX lines:" MAX #read读入一个数值
else
MAX=$1 #如果已经传参了,就把传参的$1赋值给MAX
fi
#上述脚本很巧妙地通过判断,实现了用户既可以传参输入,也可以read读入数字
i=1 #i行控制
while [ $i -le $,MAX ]
do
j=1
while [ $j -le $i ] #j行控制
do
f=$[i-1] #f=i-1是$[]计算的写法
g=$[j-1] #g=j-1是$[]计算的写法
if [ $j -eq $i ] || [ $j -eq 1 ];then
declare SUM_${i}_$j=1 #声明变量头尾都是1
else
declare A=$[SUM_${f}_$j] #取上一行的j列变量
declare B=$[SUM_${f}_$g] #取上一行的j-1列变量
declare SUM_${i}_$j=`expr $A + $B` #声明并计算当前变量的值
fi
echo -en $[SUM_${f}_$j]] " " #输出当前变量
let j++ #let运算用法
done #换行
echo #let运算用法
let i++
done
基于Shell变量输入read命令的运算实践
read命令基础
Shell变量除了可以直接复制或脚本传参外,还可以使用read命令从标准输入中获得,read为bash内置命令,可通过hlep read查看帮助

read的读入功能就相当于交互式接受用户输入,然后给变量赋值
范例:把前面加减乘除计算传参的脚本改成read方式读入整数变量
[root@adminset 05]# cat test1.sh #!/bin/bash read -t 15 -p "please input two number:" 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))" echo "a%b=$(($a%$b))"
执行结果如下:
[root@adminset 05]# sh test1.sh please input two number:10 5 a-b=5 a+b=15 a*b=50 a/b=2 a**b=100000 a%b=0
范例:以read命令读入及传参的综合企业案例

[root@adminset 05]# cat test2.sh
#!/bin/bash
#no1
read -t 15 -p "please input two number:" a b
[ ${#a} -le 0 ] && { #利用条件表达式,根据变量值的长度是否小于0,来确定第一个数是否为空
echo "the first num is null"
exit 1
}
[ ${#b} -le 0 ] && { #利用条件表达式,根据变量值的长度是否小于0,来确定第二个数是否为空
echo "the second num is null"
exit 1
}
#no2
expr $a + 1 &>/dev/null
RETVAL_A=$?
expr $b + 1 &>/dev/null
RETVAL_B=$?
if [ $RETVAL_A -ne 0 -o $RETVAL_B -ne 0 ];then
echo "one of the num is not num,pls input again."
exit 1
fi
#no3
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@adminset 05]# sh test2.sh please input two number:5 6 a-b=-1 a+b=11 a*b=30 a/b=0 a**b=15625 a%b=5
再来思考一下:如何将上述read读入改用脚本传参的方法来实现呢?
[root@adminset 05]# cat read1.sh
#!/bin/bash
a=$1
b=$2
Usage(){
echo $"USAGE:sh $0 num1 num2"
exit 1
}
if [ $# -ne 2 ];then
Usage
fi
expr $a + 1 >/dev/null 2>&1
[ $? -ne 0 ] && Usage
expr $b + 0 >/dev/null 2>&1 #这个地方使用的加0,是为了防止b为0而导致除数为0
[ $? -ne 0 ] && Usage
#no3
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))"
if [ $b -eq 0 ] #这个地方b做了个判断,防止被除数为0,算是个保险吧,可能用不上
then
echo "your input does not allow to run."
echo "a/b =error"
echo "a%b =error"
else
echo "a/b =$(($a/$b))"
echo "%b =$(($a%$b))"
fi
执行结果:
[root@adminset 05]# sh read1.sh 3 7 a-b=-4 a+b=10 a*b=21 a/b=0 a**b=2187 a%b=3 a/b =0 a%b =3 [root@adminset 05]# sh read1.sh USAGE:sh read1.sh num1 num2 [root@adminset 05]# sh read1.sh 1 luoahong USAGE:sh read1.sh num1 num2 [root@adminset 05]# sh read1.sh 8 0 a-b=8 a+b=8 a*b=0 read1.sh: line 19: 8/0: division by 0 (error token is "0")
作者:罗阿红
出处:http://www.cnblogs.com/luoahong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

浙公网安备 33010602011771号