Shell中的算术运算与条件语句(条件测试、if语句、case语句)

158 阅读11分钟

Shell允许在某些情况下对算术表达式进行求值,比如:let和declare 内置命令,(( ))复合命令和算术扩展。求值以固定宽度的整数进行,不检查溢出。

注意:默认情况下bash只支持整数运算,不支持小数运算。

一、运算表达式

运算表达式:

 (1) expr 变量1 运算符 变量2  [运算符 变量3]...
 (2) let var=算术表达式
 (3) ((var=算术表达式)),和上一个等价
 (4) var=$[算术表达式]
 (5) var=$((算术表达式))
 (6) var=$(expr arg1 arg2 arg3 ...)
 (7) var= `expr arg1 arg2 arg3 ...`
 (8) echo '算术表达式' | bc
复制代码

运算符:

  • 加法 +
  • 减法 -
  • 乘法 \ *
  • 除法 /
  • 取余 (取模)%

运算法则:

  • 加法: num1 + num2
  • 减法:num1 - num2
  • 乘法:num1 \ * num2
  • 整除:num1 / num2
  • 取余(求模):num1 % num2 (求 num1 除以 num2 的余数)

二、运算演示

1、expr

expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串。

  • 变量和运算符之间,要用空格隔开。
  • 用反斜杠 \ 放在 shell 特定的字符前面;
  • 对包含空格和其他特殊字符的字符串要用引号括起来

示例1:

 [root@localhost ~]# expr 4 + 3
 7
 [root@localhost ~]# expr 4 - 3
 1
 [root@localhost ~]# expr 4 * 3     //乘号前要加反斜杠
 12
 [root@localhost ~]# expr 10 / 2
 5
 [root@localhost ~]# expr 10 % 3     //10除以3取余数
 1
 [root@localhost ~]# expr 1 + 2 * 3    //先乘除,再加减
 7

image.png 示例2:

 [root@localhost ~]# a=1
 [root@localhost ~]# b=2
 [root@localhost ~]# expr $a + $b
 3
 [root@localhost ~]# expr $a - $b
 -1
 [root@localhost ~]# expr $a * $b
 2

image.png 示例3:

$( )和反撇号,可以调用命令的执行结果。

 [root@localhost ~]# echo $(expr 3 + 4 - 1)
 6
 [root@localhost ~]# i=$(expr 2 + 5 * 3)
 [root@localhost ~]# echo $i
 17
 [root@localhost ~]# m=`expr 1 + 2`
 [root@localhost ~]# echo $m
 3

image.png

2、let 和 (( ))

let var=算术表达式((var=算术表达式)) 效果等同。

两者都不返回结果,需要借助echo命令。

示例1:

 [root@localhost ~]# let y=1+2
 [root@localhost ~]# echo $y
 3
 [root@localhost ~]# ((z=1+2))
 [root@localhost ~]# echo $z
 3

image.png 示例2:

 [root@localhost ~]# a=30
 [root@localhost ~]# b=20
 [root@localhost ~]# let cc=$a+$b      //加法
 [root@localhost ~]# echo $cc
 50
 [root@localhost ~]# let dd=$a-$b      //减法
 [root@localhost ~]# echo $dd
 10
 [root@localhost ~]# let ee=$a*$b      //乘法
 [root@localhost ~]# echo $ee
 600
 [root@localhost ~]# let ff=$a%$b     //取余数
 [root@localhost ~]# echo $ff
 10
 [root@localhost ~]# let gg=$a/$b     //整除的商
 [root@localhost ~]# echo $gg
 1

image.png

3、$[ ]$(( ))

$[ ] 和 $(( ))效果相同,且都支持对变量进行运算。

 [root@localhost ~]# echo $[10+3]
 13
 [root@localhost ~]# echo $[10-3]
 7
 [root@localhost ~]# echo $[10*3]
 30
 [root@localhost ~]# echo $[10/3]
 3
 [root@localhost ~]# echo $[10%3]
 1
 [root@localhost ~]# a=2
 [root@localhost ~]# b=5
 [root@localhost ~]# echo $[a+b]
 7
 [root@localhost ~]# echo $[a*b]
 10
 [root@localhost ~]# echo $((a+b))
 7
 [root@localhost ~]# echo $((a*b))
 10

image.png

image.png

三、小数运算(浮点数运算)

1、使用bc计算器

Bash内置了对整数运算的支持,但是并不支持浮点运算,而 bc 计算器可以很方便的进行浮点运算。

  • 支持交互式和非交互式两种方式。
  • 使用scale=n可以指定精度,即小数点后的位数。要写在算术表达式之前。
  • 非交互式运算,使用 echo "算术表达式" | bc。 多个算术表达式之间用分号隔开,例如:echo '1+1;2+2" | bc。

示例1:

交互式运算

 [root@localhost ~]# 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*1.1            //输入1.1*1.1,敲回车
 1.2                //返回结果
 3.3+3.3            
 6.6
 scale=2           //指定精度,小数点后显示2位
 1.1*1.1           //输入1.1*1.1,敲回车
 1.21              //显示2位小数
 quit              //退出计算器
 [root@localhost ~]#

image.png 示例2:

非交互式运算,使用:echo "算术表达式" | bc。

使用scale指定精度时,要写在算术表达式之前。

 [root@localhost ~]# echo "1.1+1.1" |bc
 2.2
 [root@localhost ~]# echo "2+2.2;3.3+3.3" |bc    //多个算术表达式之间用分号隔开
 4.2
 6.6
 [root@localhost ~]# echo "scale=2;1.5*1.5;3.6*3.6" |bc   //scale=2指定小数点后显示2位
 2.25
 12.96
 [root@localhost ~]# echo "scale=3;10/2" |bc    //scale=3指定小数点后显示3位
 5.000

image.png

2、使用awk命令

使用awk进行浮点数的运算,运算结果最多显示6个有效数字。

格式:awk "BEGIN{print 算术表达式}"

示例:

 [root@localhost ~]# awk "BEGIN{print 6.5+3.4}"
 9.9
 [root@localhost ~]# awk "BEGIN{print 6.5-3.4}"
 3.1
 [root@localhost ~]# awk "BEGIN{print 6.5*3.4}"
 22.1
 [root@localhost ~]# awk "BEGIN{print 6.5/3.4}"
 1.91176
 [root@localhost ~]# awk "BEGIN{print (6.5-3.4)*7}"     //混合运算
 21.7

image.png

五、变量的自增和自减

简写表达式等同于
let i++i=$[$i+1]
let i--i=$[$i-1]
let i+=2i=$[$i+2]
let i-=2i=$[$i-2]
let i*=2i=$[$i*2]
let i/=2i=$[$i/2]
let i%=2i=$[$i%2]
示例1:

使用分号,可以在一行执行多个命令。

 [root@localhost ~]# i=1
 [root@localhost ~]# let i++        //i1
 [root@localhost ~]# echo $i
 2
 [root@localhost ~]# let i--       //i1
 [root@localhost ~]# echo $i
 1
 [root@localhost ~]# let i+=2      //i2
 [root@localhost ~]# echo $i
 3
 [root@localhost ~]# let i*=3;echo $i       //i3
 9
 [root@localhost ~]# let i/=3;echo $i       //i除以3 
 3
 [root@localhost ~]# let i%=2;echo $i       //i除以2后取余数
 1

image.png 示例2:

比较 i++ 和 ++i:

i++ 是先赋值再自增; ++i 是自增后再赋值。

 [root@localhost ~]# i=1;let i++; echo $i
 2
 [root@localhost ~]# i=1;let ++i; echo $i
 2
 [root@localhost ~]# i=100;let z=i++; echo $i $z   //i++是先赋值给z后再自增
 101 100
 [root@localhost ~]# i=100;let z=++i; echo $i $z   //++i是先自增后再赋值给z
 101 101

image.png

五、生成随机数

使用 echo $[RANDOM%n] 可以生成随机数,n为正整数。

对 n 取余数的范围是 [0,n-1]。

  • echo $[RANDOM%10]生成的随机数范围为 [0,9]
  • 如果希望包含10的话,可以echo $[RANDOM%11],则随机数范围为 [0,10]。
  • 如果希望随机数范围都为正整数,即不包含0的话,可以echo $[RANDOM%10+1],此时随机数范围为[1,10]。
 # 要求生成20以内的随机数,不包括20
 [root@localhost ~]# echo $[RANDOM % 20]
 12
 [root@localhost ~]# echo $[RANDOM % 20]
 0
 [root@localhost ~]# echo $[RANDOM % 20]
 7
 ​
 # 要求生成15以内的正整数,包括15
 [root@localhost ~]# echo $[RANDOM%15+1]
 9
 [root@localhost ~]# echo $[RANDOM%15+1]
 14
 [root@localhost ~]# echo $[RANDOM%15+1]
 8

image.png

image.png

六、条件测试语句

要使Shell脚本程序具备一定的“智能”,面临的第一个问题就是如何区分不同的情况以确定执行何种操作。Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时表示成功,否则(非0值)表示失败或异常。

使用专门的测试工具——test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为0表示条件成立)。

使用test测试命令时,有以下两种形式:

 格式一: test 条件表达式
 ​
 格式二: [ 条件表达式 ]
 ​
 #注意:每一项之间要有空格,格式二更常用
复制代码

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成。

测试过程,实现评估布尔声明,以便用在条件性环境下进行执行:

  • 若为真,则状态码变量 $? 返回0
  • 若为假,则状态码变量 $? 返回非0

1、文件测试

文件测试格式

 格式一: test 操作符 表达式
 ​
 格式二: [ 操作符 表达式 ]  

常用的文件测试操作符:

操作符作用
-d测试文件是否为目录文件(Directory)
-f测试文件是否为普通文件(File)
-e测试目录或文件是否存在(Exist)。建议使用-e,-a可能不准确。
-a测试目录或文件是否存在(Exist)
-r测试当前用户是否有权限读取(Read)
-w测试当前用户是否有权限写入(Write)
-x测试当前用户是否有权限执行(eXcute)
-L测试是否为符号链接(软链接文件)
-nt判断文件A是否比文件B新
-ot判断文件A是否比文件B旧
-ef判断两个文件是否为同一文件。可用于硬链接,主要判断两个文件是否指向同一个inode。
属性测试补充:
操作符作用
---------------------------
-s FILE判断文件是否存在且非空
-t fdfd 指定文件描述符是否在某终端已经打开
-N FILE文件自从上一次被读取之后是否被修改过
-O FILE当前有效用户是否为文件属主
-G FILE当前有效用户是否为文件属组
示例1:
 [root@nimxx ~]# test -d /etc/      //测试是否为目录
 [root@nimxx ~]# echo $?
 0                                 //状态码返回0,表示为真,是目录
 [root@nimxx ~]# [ -d /etc/ ]       //测试是否为目录
 [root@nimxx ~]# echo $?
 0
 [root@nimxx ~]# test -f /etc/sysconfig     //测试是否为普通文件
 [root@nimxx ~]# echo $?
 1                                        //状态码返回1,表示为假,不是普通文件
 [root@nimxx ~]# [ -f /etc/sysconfig ]     //测试是否为普通文件
 [root@nimxx ~]# echo $?
 1

示例2:

-e和-a都可以测试文件是否存在,但和 !(取反)连用时,-a可能不准确,建议使用-e

 [root@nimxx ~]# [ -e /etc/shadow ]     //测试文件是否存在
 [root@nimxx ~]# echo $?
 0
 [root@nimxx ~]# [ -a /etc/shadow ]     //测试文件是否存在
 [root@nimxx ~]# echo $?
 0
 [root@nimxx ~]# [ ! -a /etc/shadow ];echo $?     //测试文件是否不存在,判断结果有误
 0
 [root@nimxx ~]# [ ! -e /etc/shadow ];echo $?     //测试文件是否不存在
 1

示例3:

测试root用户对文件是否拥有读、写、执行权限。

发现root用户的读取和写入权限,不受文件的基本权限控制;但执行权限受文件基本权限控制。

 [root@nmixx ~]# ll /etc/shadow
 ----------. 1 root root 3792 3月  31 21:59 /etc/shadow
 [root@nmixx ~]# [ -r /etc/shadow ]     //测试root用户对文件是否拥有读取权限
 [root@nmixx ~]# echo $?
 0
 [root@nmixx ~]# [ -w /etc/shadow ]     //测试root用户对文件是否拥有写入权限
 [root@nmixx ~]# echo $?
 0
 [root@nmixx ~]# [ -x /etc/shadow ]     //测试root用户对文件是否拥有执行权限
 [root@nmixx ~]# echo $?
 1

示例4:

测试软链接时,目录名称后面不要加"/",不然会被判断为目录文件。

 [root@nmixx /]# ls -dl /bin
 lrwxrwxrwx. 1 root root 7 3月   8 19:13 /bin -> usr/bin    //该文件为软链接文件
 [root@nmixx /]# [ -L /bin ]        //测试是否为软链接,是
 [root@nmixx /]# echo $?
 0
 [root@nmixx /]# [ -L /bin/ ]       //测试是否为软链接,不是
 [root@nmixx /]# echo $?
 1
 [root@nmixx /]# ls -dl /bin/
 dr-xr-xr-x. 2 root root 49152 4月   5 02:15 /bin/      //该文件为目录文件

2、整数测试

整数值比较:

 [  整数变量1  操作符  整数变量2  ] 
 ​
 test 整数变量1  操作符  整数变量2
复制代码

操作符:

操作符含义
-eq等于(Equal)
-ne不等于(Not Equal)
-gt大于(Greater Than)
-lt小于(Lesser Than)
-le小于或等于(Lesser or Equal)
-ge大于或等于(Greater or Equal)

示例1:

 [root@nmixx /]# [ 2 -lt 3 ]       //测试2是否小于3
 [root@nmixx /]# echo $?
 0
 [root@nmixx /]# a=5
 [root@nmixx /]# b=6
 [root@nmixx /]# [ $a -eq $b ]     //测试变量a是否等于变量b
 [root@nmixx /]# echo $?
 1

示例2:

查询当前目录下的文件数量是否大于10,如果大于,则进行提示。

 [root@nmixx ~]# ls | wc -l
 40
 [root@nmixx ~]# test `ls |wc -l` -gt 10 && echo "文件数量大于10"
 文件数量大于10

3、字符串测试

常用的测试操作符

  • =:字符串内容相同
  • !=:字符串内容不同,! 号表示相反的意思
  • -z:字符串内容为空
  • -n:字符是否存在

字符串比较,常用的四种格式:

 [ "字符串1"  =  "字符串2"  ]   //测试字符串1和字符串2的内容是否相同
 [ "字符串1" !=  "字符串2”  ]   //测试字符串1和字符串2的内容是否不同
 [ -z "字符串" ]    //测试字符串是否为空,或者指定的变量是否为空值。(测试字符串的长度是否为零)
 [ -n "字符串" ]    //测试字符串是否存在,即是否不为空。(测试字符串的长度是否非零)
复制代码

示例1:

 [root@nmixx ~]# str1=aa
 [root@nmixx ~]# str2=bb
 [root@nmixx ~]# [ $str1 = $str2 ];echo $?    //测试变量1和变量2的值是否相同
 1
 [root@nmixx ~]# [ $USER = root ];echo $?     //测试当前用户是否为root
 0
 [root@nmixx ~]# [ $USER != root ];echo $?    //测试当前用户是否不为root
 1

 [root@nmixx ~]# [ -z $HOME ];echo $?        //测试变量HOME是否为空值
 1

示例2:

使用-z或-n测试变量时,变量需要加引号,避免有歧义而导致判断结果有误。

 [root@nmixx ~]# empty=              //设置一个空值变量
 [root@nmixx ~]# echo $empty
 ​
 [root@nmixx ~]# [ -z $empty ]       //测试变量是否为空值,为空
 [root@nmixx ~]# echo $?
 0
 [root@nmixx ~]# [ -n $empty ]       //变量没加引号,导致判断结果有误
 [root@nmixx ~]# echo $?
 0
 [root@nmixx ~]# [ -n "$empty" ]     //加了引号,判断结果正确
 [root@nmixx ~]# echo $?
 1

4、逻辑测试(短路运算)

逻辑测试用于连接多个测试条件,并返回整个表达式的值。 逻辑测试主要有"逻辑与","逻辑或","逻辑否"三种。

逻辑测试两种格式:

 格式一:[  表达式1  ]  逻辑运算符  [  表达式2  ] ...
 #例:[表达式1] && [表达式2]  等同于  [表达式1 -a 表达式2]  等同于  [[表达式1 && 表达式2]]
 #例:[表达式1] || [表达式2]  等同于  [表达式1 -o 表达式2]  等同于  [[表达式1 || 表达式2]]
 ​
 格式二:命令1  逻辑运算符  命令2  ... 
复制代码

逻辑运算符:

  • -a或&& :逻辑与,“而且”的意思,全真才为真。
  • -o或|| :逻辑或,“或者”的意思,一真即为真。
  • ! :逻辑否。

image.png 1)短路与 &&

 CMD1 && CMD2 
 全真才为真,一假即为假。      
 第一个CMD1结果为真 ,第二个CMD2必须要参与运算,才能得到最终的结果。
 第一个CMD1结果为假 ,总的结果必定为假,因此不需要执行CMD2。
 同时满足命令1 和命令2 的要求,才会返回正确。

2)短路或 ||

 CMD1 || CMD2
 一真即为真
 第一个CMD1结果为真,总的结果必定为真,因此不需要执行CMD2。
 第一个CMD1结果为假,第二个CMD2必须要参与运算,才能得到最终的结果。

1、二元运算符

示例1:

 [root@nmixx ~]# [ 1 -lt 2 ] && [ 3 -eq 4 ]    //测试1是否小于2,同时3是否等于4
 [root@nmixx ~]# echo $?
 1                                            //结果为假
 [root@nmixx ~]# [ 1 -lt 2 ] || [ 3 -eq 4 ]    //测试1是否小于2,或者3是否等于4
 [root@nmixx ~]# echo $?
 0                                            //结果为真

示例2:

[表达式1] && [表达式2] 等同于 [表达式1 -a 表达式2] 等同于 [[表达式1 && 表达式2]]

 [root@nmixx ~]# a=5
 [root@nmixx ~]# [ $a -ne 1 ]&&[ $a != 2 ]
 [root@nmixx~]# echo $?
 0
 [root@nmixx ~]# [ $a -ne 1 -a  $a != 2 ]
 [root@nmixx ~]# echo $?
 0
 [root@nmixx ~]# [[ $a -ne 1 &&  $a != 2 ]]
 [root@nmixx ~]# echo $?
 0

2、三元运算符

1、java,C语言

  • 条件表达式?a:b
  • 当条件表达式为真时,取a值;当条件表达式为假时,取b值。

2、shell

  • [ 表达式 ] && a || b
  • 当表达式为真时,取a值;当表达式为假时,取b值。
 [ 表达式 ]  && a           //相当于 if语句单分支结构
 ​
 [ 表达式 ]  && a || b      //相当于 if语句双分支结构
 ​
 [ 表达式 ]  || b           //相当于 if [表达式];else

案例应用:查看指定主机是否在线。

1)方法一:使用三元运算符

 [root@nmixx ~]# vim ping001.sh       //使用三元运算符写脚本
 #!/bin/bash
 ping -c 3 -i 0.5 -w 3 $1 &>/dev/null && echo "$1 is up" || echo "$1 is down"
 ​
 [root@nmixx ~]# bash ping001.sh 192.168.72.10      //执行脚本测试主机是否在线
 192.168.72.10 is up
 [root@nmixx ~]# bash ping001.sh 192.168.72.22
 192.168.72.22 is down

2)方法二:使用 if语句双分支结构

 [root@nmixx ~]# vim ping002.sh               //使用if语句写脚本
 #!/bin/bash
 ping -c 3 -i 0.5 -w 3 $1 &>/dev/null 
 ​
 if [ $? -eq 0 ]
 then
     echo "$1 is online" 
 else    
     echo "$1 is offline"
 fi
 ​
 [root@nmixx ~]# bash ping002.sh 192.168.72.10      //执行脚本测试主机是否在线
 192.168.72.10 is online
 [root@nmixx ~]# bash ping002.sh 192.168.72.22
 192.168.72.22 is offline

小贴士:

ping命令:

  • -c,发送包的个数。
  • -i,发送的间隔时间。
  • -w(小写),多少秒后停止ping操作。
  • -W(大写),以毫秒为单位设置ping的超时时间 。

#七、if 语句

1、if 单分支结构

单分支语句格式:

 if  判断条件
 ​
 then  条件成立的分支代码
 ​
 fi                         //条件不成立直接结

image.png 案例应用:

判断已用磁盘空间是否大于80%,如果是就报警提示。

 # 使用df命令可以查看磁盘空间使用和剩余情况
 [root@nmixx ~]# df
 文件系统                   1K-块    已用     可用 已用% 挂载点
 /dev/mapper/centos-root 17811456 5063256 12748200   29% /
 devtmpfs                  483928       0   483928    0% /dev
 tmpfs                     499848       0   499848    0% /dev/shm
 tmpfs                     499848    7264   492584    2% /run
 tmpfs                     499848       0   499848    0% /sys/fs/cgroup
 /dev/sda1                1038336  182372   855964   18% /boot
 tmpfs                      99972      12    99960    1% /run/user/42
 tmpfs                      99972       0    99972    0% /run/user/0
 [root@nmixx ~]# df |grep /dev/mapper/centos-root
 /dev/mapper/centos-root 17811456 5063288 12748168   29% /
 [root@nmixx ~]# df |grep /dev/mapper/centos-root |awk '{print $5}'
 29%
 [root@yuji ~]# df |grep /dev/mapper/centos-root |awk '{print $5}' |awk -F '%' '{print $1}'
 29
 ​
 ​
 # 编写脚本
 [root@nmixx ~]# vim diskused.sh
 #!/bin/bash
 # 判断已用磁盘空间是否大于80%,如果是则报警提示。
 ​
 used=$(df |grep /dev/mapper/centos-root |awk '{print $5}' |awk -F '%' '{print $1}')
 ​
 if [ $used -gt 80 ]
 then
    echo "警告!当前 /目录的磁盘使用率为 ${used}%"
 fi

2、if 双分支结构

双分支语句格式:

 if 判断条件
 then
     条件成立的分支代码
 else
     条件不成立的分支代码
 fi

image.png 案例应用:

检测80端口是否在监听,如果是,则提示”网站服务已在运行“;如果否,则启动httpd服务。

 # 写脚本
 [root@nmixx ~]# vim httpd80.sh
 #!/bin/bash
 # 检测80端口是否在监听,如果是,则提示”网站服务已在运行“;如果否,则启动httpd服务。
 ​
 netstat -ntap | grep :80 &> /dev/null
 ​
 if [ $? -eq 0 ]
 then
     echo "网站服务已在运行"
 else
     if rpm -q httpd &> /dev/null
     then
         echo "正在启动httpd服务"
         systemctl start httpd
     else
         echo "正在安装并启动httpd服务"
         yum install httpd -y &> /dev/null
         systemctl start httpd &> /dev/null
    fi
 fi
         
 # 执行脚本
 [root@nmixx ~]# bash httpd80.sh       //检测到未安装httpd服务,自动安装
 正在安装并启动httpd服务
 [root@nmixx ~]# rpm -q httpd          //查看软件包是否安装,已安装
 httpd-2.4.6-97.el7.centos.5.x86_64
 [root@nmixx ~]# bash httpd80.sh      //httpd服务已运行
 网站服务已在运行

3、if 多分支结构

多分支语句格式:

 if 判断条件1
 then
     条件1为真的分支代码
 ​
 elif 判断条件2
 then
     条件2为真的分支代码
 ​
 elif 判断条件3
 then
     条件3为真的分支代码
 ​
 ...
 else
     以上条件都为假的分支代码
 ​
 fi

image.png 案例应用:

查看当前时间点,根据不同时间范围输出不同问候语。

  • 6点-10点,输出早上好;
  • 11点-13点,输出中午好;
  • 14点-18点,输出下午好;
  • 19点-22点, 输出晚上好;
  • 其他时间,休息时间。
 [root@nmixx ~]# date          //查看当前详细时间
 2022年 04月 10日 星期日 15:01:25 CST
 [root@nmixx ~]# date +%H      //查看当前时间在哪个小时(范围0-23)
 15
 [root@nmixx ~]# vim date.sh     //写脚本
 #!/bin/bash
 # 查看当前时间点,根据不同时间范围输出不同问候语。
 ​
 h=$(date +%H)
 ​
 if [ $h -ge 6 -a $h -le 10 ]
 then
     echo "早上好"
 elif [ $h -ge 11 -a $h -le 13 ]
 then
     echo "中午好"
 elif [ $h -ge 14 -a $h -le 18 ]
 then
     echo "下午好"
 elif [ $h -ge 19 -a $h -le 22 ]
 then
     echo "晚上好"
 else
     echo "休息时间"
 fi
 ​
 [root@nmixx ~]# bash date.sh      //执行脚本
 下午好

八、case语句

格式:

 case 变量引用 in
 模式1)
     命令分支1
     ;;
 模式2)
     命令分支2
     ;;
 ...
 *)
     默认命令分支
 esac
复制代码

注意事项:

 case支持glob风格的通配符:
 * :任意长度任意字符
 ? :任意单个字符
 [0-9] :指定范围内的任意单个字符
 | :“或者”的意思,如: a|b
复制代码

案例应用:

提示用户输入分数(0-100),判断分数范围,分出优秀、良好、及格、不及格四档。如果用户输入的分数值不在0-100之间,则提示重新输入。

 # 写脚本
 [root@localhost ~]# vim gradediv.sh
 #!/bin/bash
 #提示用户输入分数(0-100),判断分数范围,分出优秀、良好、及格、不及格四档。
 #如果用户输入的分数值不在0-100之间,则提示重新输入。
 ​
 read -p "请输入你的分数(0-100):" grade
 ​
 case $grade in
 100)
     echo "你很优秀"
     ;;
 [89][0-9])
     echo "你表现良好"
     ;;
 [67][0-9])
     echo "你及格了"
     ;;
 [0-9]|[1-5][0-9])
     echo "你不及格"
     ;;
 *)
     echo "输入有误,请重新输入0-100"
     bash $0
 esac
 ​
 # 执行脚本
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):0
 你不及格
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):33
 你不及格
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):67
 你及格了
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):92
 你表现良好
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):100
 你很优秀
 [root@localhost ~]# bash gradediv.sh
 请输入你的分数(0-100):300
 输入有误,请重新输入0-100
 请输入你的分数(0-100):85
 你表现良好
复制代码

九、总结

常用的运算表达式:

 # 常用的四个运算表达式:
 i=$(expr 12 * 5 )
 i=$((12*5))
 i=$[12*5]
 let i=12*5
 ​
 # 变量的自增和自减等
 let i++    等同于 i=$[$i+1]
 let i--    等同于 i=$[$i-1]
 let i+=2   等同于 i=$[$i+2]
 let i-=2   等同于 i=$[$i-2]
 let i/=2   等同于 i=$[$i/2]
 ​
 # 生成随机数
 echo $[RANDOM%n]    //生成n以内的随机数,不包括n

易错总结

  1. 测试文件是否存在时,建议使用-e。如:[ -e /etc/passwd ]
  2. root用户的读取和写入权限,不受文件的基本权限控制;但执行权限受文件基本权限控制。
  3. 测试软链接时,目录名称后面不要加"/",不然会被判断为目录文件。如:[ -L /bin ]
  4. 使用-z或-n测试变量时,变量需要加引号,避免有歧义而导致判断结果有误。如:[ -n "$empty" ]