返回顶部

zhangfd

个人博客,仅供学习使用

导航

shell 编程 05 -- 变量的数值计算实践(read、let、expr、bc、declare、awk、杨辉三角)

变量的数值计算实践

5.1 算术运算符

常见的算术运算符号

算术运算符 意义
+ 、- 加、减
*、/、% 乘、除、取余(取模)
** 幂运算
++、-- 自增、自减
!、&&、|| 逻辑非、逻辑与、逻辑或
<、<=、>>= 比较符号
==、!=、= 比较符号
<<、>> 向左移位、向右移位
~、| 、&、^ 按位取反、按位异或、按位与、按位或
=、+=、-=、*=、/=、%= 赋值运算符,a+=1等价于a=a+1

shell中常见的算术运算命令

运算操作符与运算命令 意义
(()) 整数运算
let 整数运算,类似于(())
expr 整数运算,有额外功能
bc 适合整数和小数运算
$[] 整数运算
awk 适合整数和小数运算
declare 定义变量值和属性,-i参数可用于定义整数变量做运算

5.2 双小括号"(())"整数数值运算命令


双小括号“(())”的作用是进行数值运算与数值比较,它的效率很高,用法灵活,是企业场景运维人员经常采用的运算操作符


双小括号“(())”的操作方法

运算操作符与运算命令 意义-- 只能做整数运算
((i=i+1)) 将i+1的结果赋值给i;echo $((i=i+1))输出结果
i=\(((i+1)) | 在(())前加\)符,表示将运算结果赋值给i
((8>7&&5==5)) 比较操作,可加入逻辑符号,用于条件判断
echo $((2+1)) 在(())前加$,可直接输出运算表达式的运算结果

双小括号“(())”数值运算实践

## 数值运算
[root@zabbix ~]# a=8
[root@zabbix ~]# echo $((a=a+1))
9
[root@zabbix ~]# echo $((a+=1))
10
[root@zabbix ~]# echo $a
10
[root@zabbix ~]# echo $((a**2))
100
--------------------------------------
## 比较判断
[root@zabbix ~]# echo $((3<8))  --- 结果为真,输出1
1
[root@zabbix ~]# echo $((3>8))  --- 结果为假,输出0
0
[root@zabbix ~]# echo $((3==3))  --- 结果为真,输出1
1
[root@zabbix ~]# if ((8>7&&5==5)) --- 作为判断条件
> then
> echo yes
> fi
yes	--- 输出结果
[root@zabbix ~]#
-------------------------------------------------------
## 自增自减
[root@zabbix ~]# a=10
[root@zabbix ~]# echo $((a++))   -- a++,表示先输出a的值10,a再自增1,a=11
10
[root@zabbix ~]# echo $a
11
[root@zabbix ~]# a=11
[root@zabbix ~]# echo $((a--))   -- a--,表示先输出a的值111,a再自减1,a=10
11
[root@zabbix ~]# echo $a
10
[root@zabbix ~]# a=10
[root@zabbix ~]# echo $((++a))   -- ++a,表示先输出a+1的值,a再自增1=11
11
[root@zabbix ~]# echo $a
11
[root@zabbix ~]# a=11
[root@zabbix ~]# echo $((--a))   -- --a,表示先输出a-1的值,a再自减1=10
10
[root@zabbix ~]# echo $a
10
--执行echo $((a++))和echo $((a--))命令输出整个表达式时,输出的值即为a的值,表达式执行完毕后,会对a进行++、--的运算,
--而执行echo $((++a))和echo $((--a))命令输出整个表达式时,会先对a进行++、--的运算,然后再输出表达式的值,即为a运算后的值。

5.2.3 read 方式实现简单计算器

read 方式实现简单计算器,等价于echo $((num1 * num2))

[root@zabbix 0506]# cat read.sh 
#!/bin/bash
# add,sub,multi,divide caculate by moox.
print_usage(){
    printf "Please enter an integer\n"
    exit 1
}
read -p "Please input first number:" firstnum
if [ -z $firstnum ] || [ -n "`echo $firstnum|sed 's/[0-9]//g'`" ]
    then 
	print_usage
fi
read -p "Please input the aperations:" operators
if [ "$operators" != "+" ] && [ "$operators" != "-" ]&& [ "$operators" != "*" ]&&[ "$operators" != "/" ]
    then
	echo "please input {+|-|*|/}"
	exit 2
fi
read -p "Please input second number:" secondnum
if [ -z $secondnum ] || [ -n "`echo $secondnum|sed 's/[0-9]//g'`" ]
    then
        print_usage
fi
echo "${firstnum}${operators}${secondnum}=$((${firstnum}${operators}${secondnum}))"
-------------------
## 等价用法
[root@zabbix 0506]# cat cacu.sh 
echo $(($1))
[root@zabbix 0506]# sh cacu.sh "2 * 100"
200

5.3 let 运算命令的用法


let运算命令的语法格式为:let赋值表达式
let赋值表达式的功能等同于“((赋值表达式))”


5.3.1 用法:

[root@zabbix ~]# unset i
[root@zabbix ~]# i=2
[root@zabbix ~]# let i=i+8
[root@zabbix ~]# echo $i
10

5.3.2 let应用案例:监控Web服务状态

监控Web服务状态,如果访问两次均失败,则报警(let应用案例)

[root@zabbix 0506]# cat check_url.sh 
#!/bin/bash
CheckUrl(){
  timeout=5
  fails=0
  success=0
  while true
  do
	wget --timeout=$timeout --tries=1 http://oldboy.blog.51cto.com -q -O /dev/null
	if [ $? -ne 0 ]
	then
		let fails=fails+1
	else
		let success=success+1
	fi      
	if [ $success -ge 1 ]
	then
		echo success
		exit 0
	fi
	if [ $fails -le 2 ]
	then
		Critical="sys is down."
		echo $Critical|tee|mail -s "$Critical" 2144865225@qq.com
		exit 2
	fi
  done
}
CheckUrl
[root@zabbix 0506]# sh check_url.sh 
success

5.4 expr命令的用法


expr(evaluate(求值)expressions(表达式))命令既可以用于整数运算,也可以用于相关字符串长度、匹配等的运算处理。


5.4.1 expr用于计算语法:expr Expression

[root@zabbix 0506]# expr 2+2
2+2
[root@zabbix 0506]# expr 2 + 2
4
[root@zabbix 0506]# expr 2 - 2
0
[root@zabbix 0506]# expr 2 * 2
expr: syntax error
[root@zabbix 0506]# expr 2 \* 2
4
[root@zabbix 0506]# expr 2 / 2
1
## 要注意,在使用expr时:
运算符及用于计算的数字左右都至少有一个空格,否则会报错。
使用乘号时,必须用反斜线屏蔽其特定含义,因为Shell可能会误解星号的含义。

5.4.2 expr配合变量计算

expr在Shell中可配合变量进行计算,但需要用反引号将计算表达式括起来。

[root@zabbix 0506]# i=5
[root@zabbix 0506]# i=`expr $i + 6`
[root@zabbix 0506]# echo $i
11

5.4.3 expr 实例:判断变量值是否为整数


判断一个变量值或字符串是否为整数:利用以expr做计算时变量或字符串必须是整数的规则,把一个变量或字符串和一个已知的整数(非0)相加,看命令返回的值是否为0。如果为0,就认为做加法的变量或字符串为整数,否则就不是整数


  1. 通过expr判断变量或字符串是否为整数。
[root@zabbix 0506]# i=5
[root@zabbix 0506]# expr $i + 6
11							-- 可将结果> /dev/null,不做输出
[root@zabbix 0506]# echo $?
0			--- 结果为0
[root@zabbix 0506]# i=oldboy
[root@zabbix 0506]# expr $i + 6
expr: non-integer argument	-- 可将结果> /dev/null,不做输出
[root@zabbix 0506]# echo $?
127			--- 结果非0
  1. 通过传参判断输出内容是否为整数
[root@zabbix 0506]# cat expr.sh 
#!/bin/bash
expr $1 + 1 > /dev/null 2>&1
[ $? -eq 0 ] && echo int || echo chars
-----------------------------------------------
[root@zabbix 0506]# sh expr.sh  11
int
[root@zabbix 0506]# sh expr.sh aa
chars
  1. 通过read读入持续等待输入例子
[root@zabbix 0506]# cat read_expr.sh 
#!/bin/bash
while true
do
    read -p "Pls input :" a
    expr $a + 1 >/dev/null 2>&1
    [ $? -eq 0 ] && echo int ||echo chars
done
-------------------------------------------------
[root@zabbix 0506]# sh read_expr.sh 
Pls input :ss
chars
Pls input :277
int
Pls input :^C

5.4.4 expr的特殊用法(扩展名判断)

  1. 通过expr判断文件扩展名是否符合要求
[root@zabbix 0506]# cat expr_end.sh 
#!/bin/bash
if expr "$1" : ".*\.pub" &>/dev/null
  then 
    echo "you are using $1"
else
    echo "please use *.pub file."
fi
----------------------------------------
[root@zabbix 0506]# sh expr_end.sh aa
please use *.pub file.
[root@zabbix 0506]# sh expr_end.sh aa.pub
you are using aa.pub
[root@zabbix 0506]# 
  1. 使用expr命令实现系统ssh服务自带的ssh-copy-id公钥分发脚本。
[root@zabbix 0506]# cat ssh-copy-id.sh 
#!/bin/bash
echo "$0 $1 $2 $3 "
if [ "-i" = "$1" ];then
    shift
    echo "$1 $2"
    if [ -n "$2" ];then
        if expr "$1" : ".*\.pub" &>/dev/null;then
	  ID_FILE="$1"
	else
	  ID_FILE="$1.pub"
	fi
	echo $ID_FILE
    fi
fi
--------------------------------------------------------------------
[root@zabbix 0506]# sh ssh-copy-id.sh -i aa root@172.16.1.31:~/
ssh-copy-id.sh -i aa root@172.16.1.31:~/ 
aa root@172.16.1.31:~/
aa.pub
  1. expr 实现Shell脚本,打印下面语句中字符数不大于6的单词

I am oldboy linux,welcome to our training.

for n in `echo "I am oldboy linux,welcome to our training."|tr ",|." " "`
do
	if [ `expr length "$n"` -le 6 ]
		then
		echo $n
	fi
done

5.5 bc命令的用法

5.5.1 bc作为计算器来应用,直接bc命令

[root@zabbix 0506]# 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'. 
45-14*515-47+4
-7208

5.5.2 bc作为命令行来应用

[root@zabbix 0506]# echo 3+2|bc
5
[root@zabbix 0506]# echo 3+2.556|bc
5.556
[root@zabbix 0506]# echo "scale=3;3/2.556"|bc
1.173
[root@zabbix 0506]# echo "scale=7;3/2.556"|bc
1.1737089

5.5.3 bc计算输出1+2+…+10

# 通过一条命令计算输出1+2+3+…+10的表达式,并计算出结果,请使用bc命令计算。
# 输出内容如1+2+3+4+5+6+7+8+9+10=55
[root@zabbix 0506]# echo "`seq -s "+" 10`=`seq -s "+" 10|bc`"
1+2+3+4+5+6+7+8+9+10=55	

5.6 awk 实现计算


利用awk进行运算的效果也很好,适合小数和整数,特别是命令行计算,尤其是小数,运算很精确,好用。来看个示例,如下:


[root@zabbix 0506]# echo "3 9"|awk '{print ($1-$2)/4}'
-1.5

5.7 declare(同typeset)命令的用法

使用typeset定义整数变量,直接进行计算

[root@zabbix 0506]# declare -i A=30 B=7	## declare -i参数可以将变量定义为整形
[root@zabbix 0506]# A=A+B				## 已声明是整形,可以直接计算
[root@zabbix 0506]# echo $A
37

5.8 $[] 符号的运算实例

5.8.1 打印数学杨辉三角

[root@zabbix 0506]# cat yanghsj.sh 
#!/bin/bash
if (test -z $1)						-- 判断传参的长度是否为0
  then
    read -p "Input Max Lines:" MAX	-- 读入参数
  else
    MAX=$1							-- 已经传参,则赋值
fi
i=1									-- 初始行为1
while [ $i -le $MAX ]				-- 行数控制
do 
    j=1								-- 初始列为1
    while [ $j -le $i ]				-- 列数控制,列数小于等于行数
    do
		f=$[i-1]					-- 取位置:当前行的上一行
		g=$[j-1]					-- 取位置:当前列的前一列
		if [ $j -eq $i ]||[ $j -eq 1 ]	-- 控制首列值(j=1),尾列值(j=i)
	  	then
	      	declare SUM_${i}_$j=1		-- 控制每行的第一列和最后一列值都是1
		else
	    	declare  A=$[SUM_${f}_$g]	-- 取值:上一行前一列的值
	    	declare  B=$[SUM_${f}_$j]	-- 取值:上一行当前列的值
	    	## 取值:当前行当前列的值=上一行前一列的值+上一行当前列的值
	    	declare  SUM_${i}_$j=`expr $A + $B`	
		fi
		echo -en $[SUM_${i}_${j}]		-- 不换行输出每行每列的值
		let j++							-- 列值+1
    done
    echo 								-- 取完每行的所有列值,输出换行
    let i++								-- 行值+1
done

5.9 基于shell变量输入read命令的运算实践


语法格式:read [参数] [变量名]
常用参数如下。
-p prompt:设置提示信息。
-t timeout:设置输入等待的时间,单位默认为秒


  1. 功能演示:
# -t 参数指定等待时间,10秒后退出读取
# -p 参数指定提示信息
# 不使用参数时,直接跟变量
[root@zabbix 0506]# read -t 10 -p "please input a num:"  num1
please input a num: 100
[root@zabbix 0506]# echo $num1
100
[root@zabbix 0506]# read aa bb
1001 1002
[root@zabbix 0506]# echo $aa ;echo $bb
1001
1002
  1. read -p 功能可用echo -n 实现
[root@zabbix 0506]# echo -n "please input a num:"  && read num1
please input a num:100
[root@zabbix 0506]# echo $num1
100

posted on 2020-05-06 11:19  zhangfd  阅读(433)  评论(0编辑  收藏  举报