Shell脚本——条件语句【if、case】

155 阅读4分钟

本章结构:

  • 条件测试
    • 文件测试与整数测试
    • 字符串测试与逻辑测试
  • if语句
    • if单分支语句
    • if双分支语句
    • if多分支语句
  • case分支语句

一、 条件测试

1. 文件测试

文件测试格式:

格式一: `test 操作符 表达式`
         test命令用来测试表达式是否成立,若成立返回0,否则返回其他数值

格式二:` [ 操作符 表达式 ] `  
         注意前后空格,否则会失败
         
测试是否成功使用 `echo $?` 返回值

操作符:

操作符  作用
-d测试是否为目录(Directory)
-e测试目录或文件是否存在(Exist)   建议使用-e
-a测试目录或文件是否存在(Exist)
-f测试是否为文件(File)
-r测试当前用户是否有权限读取(Read)
-w测试当前用户是否有权限写入(Write)
-x测试当前用户是否有权限执行(eXcute)
-L测试是否为软连接文件
1`-d`
[root@node1 ~]#  test -d /var/    //测试/var/是否为目录
[root@node1 ~]#  echo $?
0                                 //状态码返回0,表示为真,是目录
[root@node1 ~]#  [ -d /var ]
[root@node1 ~]#  echo $?
02`-f`
[root@node1 ~]#  test -f /var/    //测试/var/是否为文件
[root@node1 ~]#  echo $?
1                                 //状态码返回1,表示为假,不是目录3`-e``-a`
[root@node1 ~]#  [ -e /var/log ]  //-e测试文件是否存在
[root@node1 ~]#  echo $?
0
[root@node1 ~]#  [ -a /var/log ]  //-a测试文件是否存在
[root@node1 ~]#  echo $?
0
[root@node1 ~]#  [ ! -e /var/log ];echo $?   //! -e 测试文件是否不存在
1
[root@node1 ~]#  [ ! -a /var/log ];echo $?   //! -a 测试文件是否不存在
0   //判断结果有误
-e和-a都可以测试文件是否存在,但和 !(取反)连用时,-a可能不准确,建议使用-e

例4`-r``-w``-x`
测试root用户对文件是否拥有读、写、执行权限:
[root@node1 ~]#  ll /etc/shadow
----------. 1 root root 1339 36 10:43 /etc/shadow
[root@node1 ~]#  [ -r /etc/shadow ];echo $?  //测试root用户对文件是否拥有读权限
0
[root@node1 ~]#  [ -w /etc/shadow ];echo $?  //测试root用户对文件是否拥有写权限
0
[root@node1 ~]#  [ -x /etc/shadow ];echo $?  //测试root用户对文件是否拥有执行权限
1
发现root用户的读取和写入权限,不受文件的基本权限控制;但执行权限受文件基本权限控制。

2. 整数值比较

格式 :[ 整数变量1 操作符 整数变量2 ]

常用的测试操作符:

操作符  含义
 -eq第一个数等于(Equal)第二个数
-ne第一个数不等于(Not Equal)第二个数
-gt第一个数大于(Greater Than)第二个数
-lt第一个数小于(Lesser Than)第二个数
-ge第一个数大于或等于(Greater or Equal)第二个数
-le第一个数小于或等于(Lesser or Equal)第二个数
[root@node1 ~]#  a=10
[root@node1 ~]#  b=20
[root@node1 ~]#  [ $a -lt $b ]   //a 小于 b
[root@node1 ~]#  echo $?         //测试是否正确
0   //正确
[root@node1 ~]#  [ $a -gt $b ]   //a 大于 b
[root@node1 ~]#  echo $?         //测试是否正确
1   //错误

3. 字符串测试

常用格式:

`[  字符串1 =  字符串2 ]`  测试字符串1和字符串2的内容是否相同

`[  字符串1  !=  字符串2 ]`  测试字符串1和字符串2的内容是否不同

常用的测试操作符:

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

4. 逻辑测试

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

格式 :

格式1`[  表达式1  ]  操作符  [  表达式2  ]  ... `

格式2`命令1  操作符  命令2  ...` 

常用的测试操作符:

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

唯一的组合用法:cmd1 && cmd2 || cmd3

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

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

5. 双中括号 [[ ]]

[[ expression ]] 用法:

  • == 左侧字符串是否和右侧的PATTERN相同
    • 注意:此表达式用于[[ ]]中,PATTERN为通配符\color{red}{通配符}
  • =~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
    • 注意: 此表达式用于[[ ]]中;扩展的正则表达式\color{red}{正则表达式}

6. ()和 {}

(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

`()`会开启子shell
`{ }` 不会开启子shell

[root@localhost data]#name=lc
[root@localhost data]#( name=mcl;echo $name );echo $name
lc

[root@localhost data]#name=lc
[root@localhost data]#{ name=mcl;echo $name; };echo $name
mcl

二、if 语句

1. 单分支结构

单分支语句格式:

if  条件判断的cmd
then  
条件为真的分支代码cmd1
fi                         //条件不成立直接结束

#执行条件判断的cmd,如果cmd成功执行,那么就运行cmd1,否则退出

2. 双分支结构

双分支语句格式:

 if 判断条件cmd1
 then
     条件为真的分支代码cmd2
 else
     条件为假的分支代码cmd3
 fi

#cmd1成功,执行cmd2,否则执行cmd3

示例:

1:判断内存容量
[root@node1 ~]#  vim mem.sh        //编写脚本

#!/bin/bash
mem=`free -m |grep Mem |awk ‘{print $4}’` //awk命令默认以空格为分隔符,print $4打印第四列

if  [$mem -lt 300 ];then           //判断条件:内存小于300MB
echo "内存不足,请尽快处理"          //条件为真输出 内存不足,请尽快处理
echo 3 > /proc/sys/vm/drop caches  //清理缓存
else
echo "内存正常"                     //条件为假输出 内存正常
fi

[root@node1 ~]#  bash mem.sh       //执行脚本
内存不足,请尽快处理
内存不足提示脚本.png
2:判断httpd是否存在
[root@node1 ~]#  vim h.sh         //编写脚本

#!/bin/bash

if command -v httpd &>/dev/null;then  //&>/dev/null 垃圾信息导入黑洞
echo "httpd已安装"
else
echo "httpd 未安装"
yum install&>/dev/null httpd-V
     if [ $? -eq 0 ];then         //嵌套
     echo "httpd 成功安装"
     systemctl  start  httpd
          if [ $? -eq 0 ];then    //再嵌套
          echo "启动成功"
          else
          echo "启动失败"
          fi
     else
     echo "httpd安装失败,请检查"
     fi
fi

[root@node1 ~]#  bash h.sh    //执行脚本
httpd已安装
判断httpd是否存在脚本.png

3. 多分支结构

双分支语句格式:

if 判断条件1
then
 条件1为真的分支代码

elif 判断条件2
then
 条件2为真的分支代码

elif 判断条件3
then
 条件3为真的分支代码

......
else
 以上条件都为假的分支代码

fi

示例:

[root@node1 ~]#  vim grade.sh     //编写脚本

#!/bin/bash
read -p "请输入你的考试分数:" grade

if [ $grade -ge 85 ]&& [ $grade -le 100 ]    //分数大于等于85,小于等于100
then
echo "你的成绩为$grade"
echo "你的成绩为优秀"

elif [ $grade -ge 70 ]&&[ $grade -le 84 ]    //分数大于等于70,小于等于84
then
echo "你的成绩为$grade"
echo "你的成绩为良好"

elif
[ $grade -ge 60 ]&&[ $grade -le 69 ]         //分数大于等于60,小于等于69
then
echo "你的成绩为$grade"
echo "你的成绩为合格" 

else                                        //以上条件都为假
echo "你的成绩为$grade"
echo "你的成绩不合格"
fi

[root@node1 ~]#  bash grade.sh   //执行脚本
请输入你的考试分数:88
你的成绩为88
你的成绩为优秀

三、 case 语句

语句格式:

case 变量值 in
模式1)
    命令分支1
    ;;
模式2)
    命令分支2
    ;;
...
*)
    默认命令分支
esac



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

示例1:远程连接(跳板机)

[root@localhost ~]#  vim tbj.sh   //编写脚本

#!/bin/bash
web1="192.168.204.10"
mysql="192.168.204.20"
docker="192.168.204.30"

cat <<EOF   //打印菜单
1.web1
2.mysql
3.doker
EOF

read -p "请输入数字(1-3):" num

case $num in
1)
ssh $web1  
;;
2)
ssh $mysql
;;
3)
ssh $doker
;;
*)
echo "输入有误,请重新输入"
bash $0
esac

[root@localhost ~]#  bash tbj.sh   //执行脚本
1.web1
2.mysql
3.doker
请输入数字(1-3):4
输入有误,请重新输入
1.web1
2.mysql
3.doker
请输入数字(1-3):1    //远程登录web1
The authenticity of host '192.168.204.10 (192.168.204.10)' can't be established.
ECDSA key fingerprint is SHA256:NGL8rGGG53cTly5n3T2ZebgIfifyVkSu9C96Jx1GFfI.
ECDSA key fingerprint is MD5:a6:df:04:3b:65:de:68:2d:a2:dd:27:26:1f:de:ef:9c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.204.10' (ECDSA) to the list of known hosts.
root@192.168.204.10's password: 
Last login: Sun May 12 11:02:42 2024 from 192.168.204.1   //成功登录web1
[root@node1 ~]#  exit
登出
Connection to 192.168.204.10 closed.

示例2:判断成绩等级

[root@node1 ~]#  vim score.sh   //编写脚本

#!/bin/bash
read -p "请输入你的分数" score

case $score in           //$score变量值
100)                     //100分
echo "$score 你太优秀了"
;;
[89][0-9])               //80~99分 (第一位数为8或9,第二位为0-9任意一位)
echo "$score 表现不错"
;;
[67][0-9])               //60~79分
echo "$score 你及格了" 
;;
[0-9]|[1-5][0-9])        //个位数 或者 10~59分
echo "$score 你不及格"
;;
*)
echo "输入有误"
esac

[root@node1 ~]#  bash score.sh    //执行脚本
请输入你的分数88
88 表现不错
[root@node1 ~]#  bash score.sh 
请输入你的分数101
输入有误

示例3:判断输入的是yes或no

无论多奇怪的yes或no都可以识别

[root@node1 ~]#  vim yes.sh     //编写脚本

#!/bin/bash
read -p "Do you agree(yes/no)? " INPUT
INPUT=`echo $INPUT | tr 'A-Z' 'a-z'`  //转换大小写

case $INPUT in
y|yes)
echo "You input is YES"
;;
n|no)
echo "You input is NO"
;;
*)
echo "Input fales,please input yes or no!"
esac

[root@node1 ~]#  bash yes.sh     //执行脚本
Do you agree(yes/no)? Yes
You input is YES
[root@node1 ~]#  bash yes.sh     
Do you agree(yes/no)? nO
You input is NO

示例4:工具箱

[root@localhost ~]#  vim gjx.sh    //编写脚本

#!/bin/bash

cat  <<EOF       //打印菜单工具
----系统工具箱------------
|  1.查看磁盘信息        |
|  2.查看内存信息        |  
|  3.查看cpu 信息        |  
|  4.查看网络信息        |  
|  5.查看进程信息        | 
|  6.退出工具箱          | 
----系统工具箱------------
EOF

read -p "请输入您的选择(1-6)" num
case $num in
1)
lsblk
bash $0
;;
2)
free
bash $0
;;
3)
lscpu
bash $0
;;
4)
ifocnfig
bash $0
;;
5)
ps aux
bash $0
;;
6)
exit
;;
esac

[root@localhost ~]#  bash gjx.sh   //执行脚本
----系统工具箱------------
|  1.查看磁盘信息        |
|  2.查看内存信息        |  
|  3.查看cpu 信息        |  
|  4.查看网络信息        |  
|  5.查看进程信息        | 
|  6.退出工具箱          | 
----系统工具箱------------
请输入您的选择(1-6)1  //查看磁盘信息
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   40G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   14G  0 part 
  ├─centos-root 253:0    0   10G  0 lvm  /
  └─centos-swap 253:1    0    4G  0 lvm  [SWAP]
sr0              11:0    1 1024M  0 rom  
----系统工具箱------------
|  1.查看磁盘信息        |
|  2.查看内存信息        |  
|  3.查看cpu 信息        |  
|  4.查看网络信息        |  
|  5.查看进程信息        | 
|  6.退出工具箱          | 
----系统工具箱------------
请输入您的选择(1-6)6    //退出

示例5:nginx安装

[root@localhost ~]#  vim nginx.sh   //编写脚本

#!/bin/bash
cd   /data
wget https://nginx.org/download/nginx-1.18.0.tar.gz  &>/dev/null
if [ $? -eq 0 ];then
echo  "nginx  下载成功"
else
echo  "nginx 下载失败"
exit
fi

tar  xf   nginx-1.18.0.tar.gz   
cd  nginx-1.18.0
yum install pcre-devel zlib-devel gcc gcc-c++ make   -y  &>/dev/null
if [ $? -eq 0 ];then
echo  "nginx  依赖环境安装成功"
else
echo  "nginx 依赖环境安装失败请检查"
exit
fi

./configure --prefix=/apps/nginx
make -j2
make install
if [ $? -eq 0 ];then
echo  "nginx  安装成功"
else
echo  "nginx 安装失败"
exit
fi


echo "
[Unit]
Description=nginx - high performance web server
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
ExecStart=/apps/nginx/sbin/nginx 
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
" > /usr/lib/systemd/system/nginx.service

systemctl  start nginx 
if [ $? -eq 0 ];then
echo  "nginx  启动成功"
else
echo  "nginx 启动失败"
fi

[root@localhost ~]#  bash nginx.sh   //执行脚本