02-Shell 编程之数值运算

1、变量的数值计算

1.1、仅支持整数的运算

1.1.1、echo $((数学运算表达式))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 形式一
[lepeng@centos ~]# echo $((1 + 1))
2
[lepeng@centos ~]# echo $((2*7-3/6+5))
19

# 形式二
[lepeng@centos ~]# ((test=2*8))
[lepeng@centos ~]# echo test
16

# 形式三
[lepeng@centos ~]# test=$((2*7-3/6+5))
[lepeng@centos ~]# echo $test
19

延伸产物(重要)

1
2
3
4
i++ 自增1
i-- 自减1
++i
--i

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[lepeng@centos ~]# i=1
[lepeng@centos ~]# echo $((i++))
1
[lepeng@centos ~]# echo $((i++))
2
[lepeng@centos ~]# echo $((i--))
3
[lepeng@centos ~]# echo $((i--))
2
[lepeng@centos ~]# echo $((i--))
1
[lepeng@centos ~]# echo $((++i))
1
[lepeng@centos ~]# echo $((++i))
2
[lepeng@centos ~]# echo $((++i))
3
[lepeng@centos ~]# echo $((--i))
2
[lepeng@centos ~]# echo $((--i))
1
[lepeng@centos ~]# echo $((--i))
0

1.1.2、let命令

1
2
3
4
5
6
7
8
9
[lepeng@centos ~]# i=1
[lepeng@centos ~]# i=i+1
[lepeng@centos ~]# echo $i
i+1

[lepeng@centos ~]# i=1
[lepeng@centos ~]# let i=i+1
[lepeng@centos ~]# echo $i
2

1.1.3、expr命令

  1. 整数计算
  2. 判断扩展名
  3. 判断输入是否为整数,非整数返回值为2
  4. 计算变量的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[lepeng@centos ~]# expr 1+1
1+1
[lepeng@centos ~]# expr 1 + 1
2
[lepeng@centos ~]# expr 1 * 1
expr: 语法错误
[lepeng@centos ~]# expr 1 \* 1
1

# 非整数返回值为2 示例:
[lepeng@centos ~]# expr 1 + 1
2
[lepeng@centos ~]# echo $?
0
[lepeng@centos ~]# expr -1 + 1
0
[lepeng@centos ~]# echo $?
1
[lepeng@centos ~]# expr a + 1
expr: 非整数参数
[lepeng@centos ~]# echo $?
2

1.1.4、$[]运算符

1
2
3
4
5
6
7
8
[lepeng@centos ~]# echo $[1+2]
3
[lepeng@centos ~]# echo $[1-2]
-1
[lepeng@centos ~]# echo $[1*2]
2
[lepeng@centos ~]# echo $[1/2]
0

1.1.5、typeset

1
2
3
4
[lepeng@centos ~]# typeset -i A=2017 B=2018
[lepeng@centos ~]# A=A+B
[lepeng@centos ~]# echo $A
4035

1.2、小数运算

1.2.1、bc

1
2
# 安装 bc
[lepeng@centos ~]# yum -y install bc

交互模式测试bc命令

1
2
3
4
5
6
7
[lepeng@centos ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
1+1
2
[lepeng@centos ~]# echo 1+1.1|bc
2.1

免交互模式测试bc命令

1
2
[lepeng@centos ~]# echo 'scale=6;1/3'|bc
.333333

1.2.2、awk

1
2
3
4
5
6
7
8
[lepeng@centos ~]# echo "7.7 3.8"|awk '{print ($1-$2)}'
3.9
[lepeng@centos ~]# echo "358 113"|awk '{print ($1-3)/$2}'
3.14159
[lepeng@centos ~]# echo "3 9"|awk '{print ($1+3)*$2}'
54
[root@backup scripts]# awk BEGIN'{print 1.2+3.3}'
4.5

1.3、运算相关练习题

1.3.1、【练习题】实现一个加减乘除等功能的计算器

1
2
3
4
5
6
7
8
9
10
[lepeng@centos ~]# cat jishuanqi.sh 
#!/bin/bash
#
read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" 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
[lepeng@centos ~]# sh jishuanqi.sh 
请输入第一个整数:12
请输入第二个整数:12
12 + 12 =24
12 - 12 =0
12 * 12 =144
12 / 12 =1

精简方法

1
2
3
4
[lepeng@centos ~]# vim jishuanqi2.sh 
#!/bin/bash
#
echo $(($1))

脚本执行过程:

1
2
3
4
[lepeng@centos ~]# sh jishuanqi2.sh  1+1
2
[lepeng@centos ~]# sh jishuanqi2.sh 1*9
9

1.3.2、【练习题】打印结果1+2+3+4+5+6+7+8+9+10=55

1
2
3
4
5
[lepeng@centos ~]# vim yunshuan.sh
#!/bin/bash
#
Num=`seq -s + 1 10`
echo $Num=$(($Num))

脚本执行结果

1
2
[lepeng@centos ~]# sh  yunshuan.sh
1+2+3+4+5+6+7+8+9+10=55

2 条件表达式

2.1、文件判断

常用文件测试操作符

表达式 说明
-d 文件,d的全拼为directory 文件存在且为目录则为真,即测试表达式成立
-f 文件,f的全拼为file 文件存在且为普通文件则为真,即测试表达式成立
-e 文件,e的全拼为exist 文件存在则为真,即测试表达式成立。注意区别于“-f”,-e不辨别是目录还是文件
-r 文件,r的全拼为read 文件存在且可读则为真,即测试表达式成立
-s 文件,s的全拼为size 文件存在且文件大小不为0则为真,即测试表达式成立
-w 文件,w的全拼为write 文件存在且可写则为真,即测试表达式成立
-x 文件,x的全拼为executable 文件存在且可执行则为真,即测试表达式成立
-L 文件,L的全拼为link 文件存在且为链接文件则为真,即测试表达式成立
fl -nt f2,nt 的全拼为 newer than 文件fl比文件f2新则为真,即测试表达式成立。根据文件的修改时间来计算
fl -ot f2,ot 的全拼为 older than 文件fl比文件f2旧则为真,即测试表达式成立。根据文件的修改时间来计算
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
# 判断文件是否存在
[lepeng@centos ~]# [ -f /etc/hosts ]
[lepeng@centos ~]# echo $?
0
[lepeng@centos ~]# [ -f /etc/hosts1 ]
[lepeng@centos ~]# echo $?
1


# 判断文件是否存在,返回方式
[lepeng@centos ~]# [ -f /etc/hosts ] && echo "文件存在" || echo "文件不存在"
文件存在
[lepeng@centos ~]# [ -f /etc/hosts1 ] && echo "文件存在" || echo "文件不存在"
文件不存在


# 判断目录是否存在
[lepeng@centos ~]# [ -d /tmp ] && echo "目录存在" || echo "目录不存在"
目录存在
[lepeng@centos ~]# [ -d /tmp1 ] && echo "目录存在" || echo "目录不存在"
目录不存在


# 使用变量的方法进行判断
dir=/etc1/;[ -d $dir ] && tar zcf etc.tar.gz $dir || echo "$dir目录不存在"

2.2、字符串判断

字符串测试操作符

常用字符串测试操作符 说明
-n “字符串” 若字符串的长度不为0,则为真,即测试表达式成立,n可以理解为no zero
-Z “字符串” 若字符串的长度为0,则为真,即测试表达式成立,z可以理解为zero的缩写
“串 1”== “串 2” 若字符串1等于字符串2,则为真,即测试表达式成立,可使用”==”代替”=”
“串 1” != “串 2” 若字符串1不等于字符串2,则为真,即测试表达式成立,但不能用”!==”代替”!=”

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#-z 判断字符串长度
[lepeng@centos ~]# x= ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
输入为空
[lepeng@centos ~]# x=12 ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
输入有内容


# -n 判断字符串长度
[lepeng@centos ~]# x=12 ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
输入有内容
[lepeng@centos ~]# x= ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
输入为空


# "串 1" == " 串 2 " 使用定义变量的方式进行判断
cmd=$1
[ "$cmd" == "start" ] && echo start
# 测试
[lepeng@centos ~]# cmd=start;[ "$cmd" == "start" ] && echo start
start

2.3、整数判断

整数二元比较操作符参考

在[]以及test中使用的比较符号 在(())和[[]]中使用的比较符号 说明
-eq ==或= 相等,全拼为equal
-ne != 不相等,全拼为not equal
-gt > 大于,全拼为greater than
-ge >= 大于等于,全拼为greater equal
-lt < 小于,全拼为less than
-le <= 小于等于,全拼为less equal

示例:

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
# 判断两数是否相等
[lepeng@centos ~]# [ 1 -eq 1 ]
[lepeng@centos ~]# echo $?
0
[lepeng@centos ~]# [ 1 -eq 2 ]
[lepeng@centos ~]# echo $?
1


# 大于等于
[lepeng@centos ~]# [ 11 -ge 1 ] && echo "成立" || echo "不成立"
成立


# 小于
[lepeng@centos ~]# [ 11 -lt 1 ] && echo "成立" || echo "不成立"
不成立


# 大于
[lepeng@centos ~]# [ 11 -gt 1 ] && echo "成立" || echo "不成立"
成立


# 不等于
[lepeng@centos ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
成立

2.4、逻辑符号

常用逻辑操作符

在[]和test中使用的操作符 说明 在[[]]和中使用的操作符 说明
-a [ 条件A -a 条件B ] A与B都要成立,整个表达式才成立 && and,与,两端都为真,则结果为真
-o [ 条件A -o 条件B] A与B都不成立,整个表达式才不成立 `
! ! not,非,两端相反,则结果为真
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 逻辑操作符与整数判断配合
[lepeng@centos ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
成立

# 取反
[lepeng@centos ~]# [ ! 11 -ne 1 ] && echo "成立" || echo "不成立"
不成立

# 两边都为真
[lepeng@centos ~]# [ 11 -ne 1 -a 1 -eq 1 ] && echo "成立" || echo "不成立"
成立

# 至少有一边为真
[lepeng@centos ~]# [ 11 -ne 1 -o 1 -eq 1 ] && echo "成立" || echo "不成立"
成立

感叹号的特殊用法:使用历史命令,感叹号加上history中的序号,即可执行

1
2
3
[lepeng@centos ~]# !516
ls
anaconda-ks.cfg bootime.avg setup.sh vim

2.5 【练习题】开发3个shell脚本比较2个整数大小

要求:

  1. 分别以定义变量,脚本传参以及read读入的方式写3个脚本。
  2. 用条件表达式(禁止if语句)进行判断。
  3. 将2个整数的比较结果输出到屏幕,出错需要提示。

使用定义变量方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[lepeng@centos ~]# cat panduan1.sh 
#!/bin/bash
#
NUM1=6
NUM2=2

expr 1 + $NUM1 &>/dev/null
[ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
expr 1 + $NUM2 &>/dev/null
[ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2

[ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit
[ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
[ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用传参方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[[lepeng@centos ~]# cat panduan_chuanchan.sh 
#!/bin/bash
#
[ $# -ne 2 ] && echo "UASGE $0 num1 num2 " && exit

NUM1=$1
NUM2=$2

expr 1 + $NUM1 &>/dev/null
[ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
expr 1 + $NUM2 &>/dev/null
[ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2

[ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2 && exit
[ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
[ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

使用read读入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[[lepeng@centos ~]# cat panduan_read.sh 
#!/bin/bash
#
read -p "请输入第一个整数:" NUM1
read -p "请输入第二个整数:" NUM2

expr 1 + $NUM1 &>/dev/null
[ $? -eq 2 ] && echo "$NUM1 不是整数 " && exit 2
expr 1 + $NUM2 &>/dev/null
[ $? -eq 2 ] && echo "$NUM2 不是整数 " && exit 2

[ "$NUM1" -eq "$NUM2" ] && echo "$NUM1 = $NUM2" && exit
[ "$NUM1" -gt "$NUM2" ] && echo "$NUM1 > $NUM2" && exit
echo "$NUM1 < $NUM2"

02-Shell 编程之数值运算
https://flepeng.github.io/021-Shell-02-Shell-编程之数值运算/
作者
Lepeng
发布于
2016年1月1日
许可协议