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

算术运算符

变量的数值(整数)计算

 

 

1)(())用法:(此方法很常用)**

 

范例:shell的算术运算实例如下:

1
2
3
4
5
6
7
8
[root@db01 ~]# ((a=1+2**3-4%3))
[root@db01 ~]# echo $a
8
[root@db01 ~]# ((a=1+2**3-4%3))
[root@db01 ~]# echo $a
8
[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 $a
5050

范例6:这是一个实践考试题,内容如下: 

把a,b两个变量通过命令行脚本传参的方式实现上面混合运算脚本的功能 
第一种方法:

1
2
3
4
5
6
7
8
9
#!/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 ))"

第二种方法:

1
2
3
4
5
6
7
8
9
10
[root@web02 ~]# cat abc.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 ))"

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 $i
10

范例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时:

  1. 运算符及用于计算的数字左右都至少有一个空格,否则会报错
  2. 使用称号时:必须用反斜线屏蔽其特定含义,因为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/sh
if expr "$1" ".*\.pub" &>/dev/null
then
echo "you are using $1"
else
echo "pls use *.pub file"
fi
[root@web02 ~]# sh aaa.sh oldboy
pls use *.pub file
[root@web02 ~]# sh aaa.sh oldboy.pub
you are using oldboy.pub

判断一个输入是不是数字

1
2
3
4
5
6
7
#!/bin/sh
while true
do
read -p "Pls input:" a
expr $a + 0 >/dev/null 2>&1
[ $? -eq 0 ] &&echo int||echo chars
done

如果判断是不是数字,就执行错误shars

1
2
3
4
5
6
7
8
9
10
11
12
[root@db01 scripts]# cat b.sh
#!/bin/sh
expr $1 + 1 >/dev/null 2>&1
[ $? -eq 0 ] &&echo int||echo chars
[root@db01 scripts]# sh b.sh 1
int
[root@db01 scripts]# sh b.sh 1a
chars
[root@db01 scripts]# sh b.sh 100
int
[root@db01 scripts]# sh b.sh 100abc
chars

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]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1+1
2
1+3
4
6*8
48

另一种使用bc的方式

1
2
3
4
[root@db01 scripts]# echo 1+2|bc
3
[root@db01 scripts]# echo 8-2|bc
6

inux下的bc命令可以设置结果的位数,通过scale.

1
2
3
4
5
6
7
[root@db01 scripts]# echo "scale=3;5.23 / 3.13"|bc
1.670
[root@db01 scripts]# echo "scale=2;5.23 / 3.13"|bc
1.67
比如:
echo "scale=4; 1.2323293128 / 1.1" bc -l
1.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 $i
3
可以做加法计算
[root@web02 ~]# echo 3.5+5
3.5+5
[root@web02 ~]# echo 3.5+5|bc
8.5
减法计算
[root@web02 ~]# echo 3.5-5|bc
-1.5
乘法计算
[root@web02 ~]# echo 3.5*5|bc
17.5
保留位数(bc的用处不大)
[root@web02 ~]# echo "scale=2; 3.5*5.1"|bc
17.85
[root@web02 ~]# echo "scale=2; 3*5"|bc
15
[root@web02 ~]# echo "scale=1; 3*5"|bc
15
提示: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 $i
11

提示:根据bc所具有的特殊性来看:

  1. 如果小数,则选择bc运算没有问题(老男孩推荐awk)
  2. 若是整数场景,可用(())、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 "+" " "10
1+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")
posted @ 2018-06-25 15:28  活的潇洒80  阅读(501)  评论(0)    收藏  举报