兄弟连linux基础之Shell基础(六)——条件判断、流程控制

视频参考:https://www.bilibili.com/video/BV1mW411i7Qf?from=search&seid=11812550775556654179

一、条件判断

1、按照文件类型进行判断

测试选项 作 用
-b 文件 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真)
-c文件 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真)
-d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真)
-e 文件 判断该文件是否存在(存在为真)
-f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真)
-L 文件 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真)
-p 文件 判断该文件是否存在,并且是否为管道文件(是管道文件为真)
-s 文件 判断该文件是否存在,并且是否为非空(非空为真)
-S 文件 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真)
  • 两种判断格式
ly2@DGX:~$ test -e student.txt   # 第一种,常用于人为判断
ly2@DGX:~$ echo $?               # 判断上一条语句是否正确运行,是0否非0
0
ly2@DGX:~$ [ -e student.txt ]    # 第二种,注意中括号两侧有空格,程序脚本中更常用
ly2@DGX:~$ echo $?
0
ly2@DGX:~$ [ -f /ly2/student.txt ] && echo "yes" || echo "no"
no                         # 第一个判断命令如果正确执行,则打印yes,否则打印no
ly2@DGX:~$ [ -f ./student.txt ] && echo "yes" || echo "no"
yes

2、按照文件权限进行判断

测试选项 作 用
-r 文件 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真)
-w文件 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真)
-x 文件 判断该文件是否存在,并且是否该文件拥有执行权限(有 执行权限为真)
-u 文件 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真)
-g 文件 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真)
-k 文件 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真)
ly2@DGX:~$ [ -w ./student.txt ] && echo "yes" || echo "no" # 注意中括号空格
yes                       # 所有者所属组,其他人,只要有一个有权限,则输出yes

3、两个文件之间进行比较

测试选项 作 用
文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新(如果新则为真)
文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧(如果旧则为真)
文件1 -ef 文件2 判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法
ly2@DGX:~$ ln student.txt ./sh/stu.txt   # 创建两个文件的硬链接
ly2@DGX:~$ ls -i student.txt             # 查看student.txt的inode号
25962460 student.txt
ly2@DGX:~$ ls -i ./sh/stu.txt            # 查看stu.txt的inode号
25962460 ./sh/stu.txt                    # inode相同则为硬链接
ly2@DGX:~$ ls -i ./sh
25962461 canshu1.sh  25962465 canshu4.sh  25962463 hello.sh
25962464 canshu2.sh  25962468 canshu5.sh  25962460 stu.txt
25962455 canshu3.sh  25962469 canshu6.sh  25962462 sum.sh
ly2@DGX:~$ [ student.txt -ef ./sh/stu.txt ] && echo "yes" || echo "no"   # 判断硬链接
yes

4、两个整数之间比较

测试选项 作 用
整数1 -eq 整数 2 判断整数1是否和整数2相等(相等为真)
整数1 -ne 整数 2 判断整数1是否和整数2不相等(不相等位置)
整数1 -gt 整数2 判断整数1是否大于整数2(大于为真)
整数1 -lt 整数2 判断整数1是否小于整数2(小于位置)
整数1 -ge 整数2 判断整数1是否大于等于整数2(大于等于为真)
整数1 -le 整数2 判断整数1是否小于等于整数2(小于等于为真)
ly2@DGX:~$ [ 23 -gt 22 ] && echo "yes" || echo "no"
yes

5、字符串的判断

测试选项 作 用
-z 字符串 判断字符串是否为空(为空返回真)
-n 字符串 判断字符串是否为非空(非空返回真)
字串1 ==字串2 判断字符串1是否和字符串2相等(相等返回真)
字串1 != 字串2 判断字符串1是否和字符串2不相等(不相等返回真)
ly2@DGX:~$ name=sc                                   # 给 name 变量赋值
ly2@DGX:~$ [ -z "$name" ] && echo "yes" || echo "no" # name为空返回真
no                                                   # name不为空
ly2@DGX:~$ aa=11
ly2@DGX:~$ bb=22
ly2@DGX:~$ [ "$aa"=="bb" ] && echo "yes" || echo "no"  # 判断字符串是否相等
yes

6、多重条件判断

测试选项 作 用
判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真
!判断 逻辑非,使原始的判断式取反,注意有空格
ly2@DGX:~$ aa=11
ly2@DGX:~$ [ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no"
no # -n判断变量aa是否为空,非空返回真,同时判断变量aa的是否大于23 
# 因为变量aa的值不大于23 ,所以虽然第一个判断值为真,返回的结果也是假
ly2@DGX:~$ aa=24
ly2@DGX:~$ [ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no"
yes

二、流程控制

1、if 语句

1)单分支if条件语句

if [ 条件判断式 ]; then
    程序
fi
或者
if [ 条件判断式 ]
    then
        程序
fi

单分支条件语句需要注意几个点

  • i f if 语句使用 f i fi 结尾,和一般语言使用大括号结尾不同
  • [ 条件判断式 ]就是使用 t e s t test 命令判断,所以中括号和条件判断式之间必须有空格
  • t h e n then 后面跟符合条件之后执行的程序,可以放在[ ]之后,用“;”分割。也可以换行写入,就不需要“;”了
    例子:判断分区使用率
ly2@DGX:~$ df -h | grep /dev/sda2
/dev/sda2       440G  258G  159G  62% /
ly2@DGX:~$ df -h | grep /dev/sda2 | awk '{print  $5}'
62%
ly2@DGX:~$ df -h | grep /dev/sda2 | awk '{print  $5}' | cut -d "%" -f1
62
ly2@DGX:~/sh$ vim df1.sh
#!/bin/bash 
# 统计根分区使用率
 
rate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" f1) 
# 把根分区使用率作为变量值赋予变量 rate 
 
if [ $rate -ge 80 ]  
	then         
		echo "Warning! /dev/sda3 is full!!" 
fi 
ly2@DGX:~/sh$ bash df1.sh
Warning! /dev/sda2 is full! 

2)双分支if条件语句

if [ 条件判断式 ]
    then
        条件成立时,执行的程序
    else
        条件不成立时,执行的另一个程序
fi

  • 例子1:备份mysql数据库
ly2@DGX:~/sh$ date
Mon Dec  2 10:52:53 HKT 2019
ly2@DGX:~/sh$ date +%y%m%d
191202
#!/bin/bash
# 备份 mysql 数据库
# Author: shenchao (E-mail: [email protected]
ntpdate asia.pool.ntp.org &>/dev/null # 同步系统时间
date=$(date +%y%m%d) # 把当前系统时间按照 “ 年月日 ” 格式赋予变量date 
size=$(du -sh /var/lib/mysql) # 统计mysql数据库的大小,并把大小赋予size变量

if [ -d /tmp/dbbak ]  
	then         
		echo "Date : $date!" > /tmp/dbbak/dbinfo.txt 
		echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt
		cd /tmp/dbbak         
		tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt  &>/dev/null     # 变量名作为文件名,避免覆盖,&...所有输出丢到回收站
		rm -rf /tmp/dbbak/dbinfo.txt  
	else         	
		mkdir /tmp/dbbak         
		echo "Date : $date!" > /tmp/dbbak/dbinfo.txt         
		echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt         
		cd /tmp/dbbak         
		tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt  &>/dev/null   
		rm -rf /tmp/dbbak/dbinfo.txt 
fi 
  • 备份sh文件夹
ly2@DGX:~/sh$ ls                     # 查看sh文件夹下的文件
canshu1.sh  canshu3.sh  canshu5.sh  hello.sh  if2.sh   sum.sh
canshu2.sh  canshu4.sh  canshu6.sh  if1.sh    stu.txt
ly2@DGX:~/sh$ vim if2.sh             # 编写脚本程序
#!/bin/bash
# ntpdate asia.pool.ntp.org &>/dev/null
#同步系统时间
date=$(date +%y%m%d)
size=$(du -sh ../sh)   # ?
if [ -d ./dbbak ]
        then
                echo "Date:$date!" > ./dbbak/dbinfo.txt
                echo "Data size:$size" >> ./dbbak/dbinfo.txt
                cd dbbak
                tar -zcf sh-$date.tar.gz ../../sh dbinfo.txt
        else
                mkdir dbbak
                echo "Date:$date!" > ./dbbak/dbinfo.txt
                echo "Data size:$size" >> ./dbbak/dbinfo.txt
                cd dbbak
                tar -zcf sh-$date.tar.gz ../../sh dbinfo.txt
fi
ly2@DGX:~/sh$ bash if2.sh             #  运行脚本
tar: Removing leading `../../' from member names
tar: Removing leading `../../' from hard link targets
ly2@DGX:~/sh$ ls                      # 查看sh文件夹
canshu1.sh  canshu3.sh  canshu5.sh  dbbak     if1.sh  stu.txt
canshu2.sh  canshu4.sh  canshu6.sh  hello.sh  if2.sh  sum.sh
ly2@DGX:~/sh$ cd dbbak
ly2@DGX:~/sh/dbbak$ ls
dbinfo.txt  sh-191202.tar.gz
ly2@DGX:~/sh/dbbak$ cat dbinfo.txt    # 查看dbinfo.txt时间与容量
Date:191202!
Data size:48K   ../sh
ly2@DGX:~/sh/dbbak$ tar -ztvf sh-191202.tar.gz # 查看压缩包
drwxrwxr-x ly2/ly2           0 2019-12-02 11:43 sh/
-rwxr-xr-x ly2/ly2          45 2019-11-22 10:27 sh/canshu1.sh
drwxrwxr-x ly2/ly2           0 2019-12-02 11:43 sh/dbbak/
-rw-rw-r-- ly2/ly2          33 2019-12-02 11:43 sh/dbbak/dbinfo.txt
-rw-rw-r-- ly2/ly2           0 2019-12-02 11:43 sh/dbbak/sh-191202.tar.gz
-rwxr-xr-x ly2/ly2          64 2019-11-22 09:12 sh/hello.sh
-rwxr-xr-x ly2/ly2         354 2019-11-22 11:09 sh/canshu4.sh
-rwxr-xr-x ly2/ly2         487 2019-11-22 16:15 sh/canshu6.sh
-rwxr-xr-x ly2/ly2          36 2019-11-22 10:52 sh/canshu2.sh
-rwxr-xr-x ly2/ly2         352 2019-11-22 11:49 sh/canshu5.sh
-rwxr-xr-x ly2/ly2         100 2019-11-22 10:58 sh/canshu3.sh
-rw-rw-r-- ly2/ly2         228 2019-12-02 10:43 sh/if1.sh
-rw-rw-r-- ly2/ly2          97 2019-12-01 16:44 sh/stu.txt
-rw-rw-r-- ly2/ly2         514 2019-12-02 11:41 sh/if2.sh
-rwxr-xr-x ly2/ly2         115 2019-11-22 10:43 sh/sum.sh
hrw-rw-r-- ly2/ly2           0 2019-12-02 11:43 dbinfo.txt link to sh/dbbak/dbinfo.txt
  • 例子2:判断apache是否启动
#!/bin/bash 
# Author: shenchao (E-mail: [email protected]
port=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk '{print $2}') 
# 使用 nmap 命令扫描服务器 , 并截取 apache 服务的状态 , 赋予变量 port
if [ "$port" == "open" ]  
	then   
		echo$(date) httpd is ok!>> /tmp/autostart-acc.log  
	else         
		/etc/rc.d/init.d/httpd start &>/dev/null 
		echo "$(date) restart httpd !!" >> /tmp/autostart-err.log  
fi 
ly2@DGX:~$ yum -y install nmap              # 只有管理员可以安装
You need to be root to perform this command.
ly2@DGX:~$ nmap -sT 219.223.179.39          # 网络探测端口扫描和安全审核工具
The program 'nmap' is currently not installed. To run 'nmap' please ask your administrator to install the package 'nmap'

在这里插入图片描述

3)多分支if条件语句

if [ 条件判断式1 ]
    then
        当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
    then
        当条件判断式2成立时,执行程序2
…省略更多条件
else
    当所有条件都不成立时,最后执行此程序
fi

ly2@DGX:~/sh$ vim fi3.sh
#!/bin/bash
#判断用户输入的是什么文件

read -p "Please input a filename:" file
#接收键盘输入,并赋予变量file

if [ -z "$file" ]
#判断文件是否为空
        then
                echo "Error,please input a filename"
                exit 1
elif [ ! -e "$file" ]
#判断file的值是否存在
        then
                echo "Your input is not a file!"
                exit 2
elif [ -f "$file" ]
#判断file的值是否为普通文件
        then
                echo "$file is a regular file!"
elif [ -d "$file" ]
#判断file的值是否为目录文件
        then
                echo "$file is a directory!"
else
                echo "$file is an other file!"
fi

ly2@DGX:~/sh$ bash fi3.sh             # 运行脚本
Please input a filename:canshu1.sh         # 输入文件名
canshu1.sh is a regular file!                    # canshu1是普通文件
ly2@DGX:~/sh$ bash fi3.sh             # 运行脚本
Please input a filename:dbbak              # 输入文件名
dbbak is a directory!				 # dbbak是个文件夹
ly2@DGX:~/sh$ bash fi3.sh             # 运行脚本
Please input a filename:adad               # 输入文件名
Your input is not a file!                        # adad不存在
ly2@DGX:~/sh$ echo $?
2
ly2@DGX:~/sh$ bash fi3.sh             # 运行脚本
Please input a filename:                   # 输入文件名为空
Error,please input a filename                    # 提示请输入文件名
ly2@DGX:~/sh$ echo $?
1

2、case语句

多分支 c c ase条件语句: c a s e case 语句和 i f e l i f e l s e if…elif…else 语句一样都是多分支条件语句,不过和 i f if 多分支条件语句不同的是, c a s e case 语句只能判断一种条件关系,而 i f if 语句可以判断多种条件关系。

case $变量名 in
    “值1”)
        如果变量的值等于值1,则执行程序1
        ;;
    “值2”)
        如果变量的值等于值2,则执行程序2
        ;;
    …省略其他分支…
    *)
        如果变量的值都不是以上的值,则执行此程序
        ;;
esac

ly2@DGX:~/sh$ vim case.sh
#!/bin/bash
echo '如果想飞往上海,请输入“1”'
echo '如果想飞往广州,请输入“2”'
echo '如果想飞往成都,请输入“3”'

read -t 30 -p "请选择:" cho

case "$cho" in
        "1")
                echo "飞往上海的机票已发布"
                ;;                              # 别忘了分号;
        "2")
                echo "飞往广州的机票已发布"
                ;;
        "3")
                echo "飞往成都的机票已发布"
                ;;
        *)
                echo "输入错误"
                ;;
esac
ly2@DGX:~/sh$ bash case.sh
如果想飞往上海,请输入“1”
如果想飞往广州,请输入“2”
如果想飞往成都,请输入“3”
请选择:3
飞往成都的机票已发布

3、for循环

语法一
for 变量 in 值1 值2 值3…   # 有几个值执行几次,空格间隔
    do
        程序
    done

ly2@DGX:~/sh$ cat for1.sh
#!/bin/bash
#打印时间
for time in morning noon afternoon evening
        do
                echo "This time is $time!"
        done
ly2@DGX:~/sh$ chmod 755 for1.sh
ly2@DGX:~/sh$ ./for1.sh
This time is morning!
This time is noon!
This time is afternoon!
This time is evening!
ly2@DGX:~/sh$ ls > sh.log
ly2@DGX:~/sh$ cat sh.log
canshu1.sh
……
canshu6.sh
case.sh
dbbak
fi3.sh
for1.sh
hello.sh
if1.sh
if2.sh
ls.lod
stu.txt
sum.sh
#!/bin/bash 
#批量解压缩脚本 
# Author: shenchao (E-mail: [email protected]
cd /lamp                          # lamp = linux + apache + Mysql + PHP
ls *.tar.gz > ls.log 
for i in $(cat ls.log)            # 不确定循环多少次,用变量替代
	do                 
		tar -zxf $i &>/dev/null         
	done 
rm -rf /lamp/ls.log 
ly2@DGX:~/sh$ cat for2.sh
#!/bin/bash
# 查询sh文件夹下bash脚本个数
ls *.sh > sh.log

y=1
for i in $(cat sh.log)
        do
                echo $y
                y=$(( $y + 1 ))
        done
ly2@DGX:~/sh$ bash for2.sh
1
2
3
……
ly2@DGX:~/sh$ cat sh.log
canshu1.sh
canshu2.sh
canshu3.sh
……

语法二
for (( 初始值;循环控制条件;变量变化 )) # 只有双括号括起来,才可进行加减运算
    do
        程序
    done

ly2@DGX:~/sh$ vim for3.sh
#!/bin/bash
#从1加到100
s=0
for ((i=1;i<=100;i=i+1))
        do
                s=$(($s+$i))
        done
echo "The sum of 1+2...+100 is:" $s
ly2@DGX:~/sh$ bash for3.sh
The sum of 1+2...+100 is: 5050
#!/bin/bash 
#批量添加指定数量的用户 
# Author: shenchao (E-mail: [email protected]
read -p "Please input user name: " -t 30 name
read -p "Please input the number of users: " -t 30 num  
read -p "Please input the password of users: " -t 30 pass 
if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]      
# 注意 !与z有空格,判断输入三个值是否为空(-z),空(-z=1),不空(-z=0,! -z=1)
	then         
		y=$(echo $num | sed 's/^[0-9]*$'//g')     
		# 判断num是否为数字,是的话,返回空值赋给y          
		if [ -z "$y" ]        # 如果 y 的值为空,继续运行                 
			then                 
				for (( i=1;i<=$num;i=i+1 ))
					do                           
						/usr/sbin/useradd $name$i &>/dev/null
						echo $pass | /usr/bin/passwd --stdin "$name$i" &>/dev/null
					done         
		fi   
fi 

4、while循环与until循环

1)while循环

w h i l e while 循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和 f o r for 的固定循环不太一样了。

while [ 条件判断式 ]
    do
        程序
    done

ly2@DGX:~/sh$ cat while.sh
#!/bin/bash
#从1加到100
i=1
s=0
while [ $i -le 100 ]
#如果变量i的值小于等于100,则执行循环
        do
                s=$(($s+$i))
                i=$(($i+1))
        done
echo "The sum is: $s"
ly2@DGX:~/sh$ bash for4.sh
The sum is: 5050

2)until循环

u n t i l until 循环,和 w h i l e while 循环相反, u n t i l until 循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

until [ 条件判断式 ]
    do
        程序
    done

ly2@DGX:~/sh$ cat until.sh
#!/bin/bash
#从1加到100
i=1
s=0
until [ $i -gt 100 ]
#循环直到变量i的值大于100,就停止循环
        do
                s=$(($s+$i))
                i=$(($i+1))
        done
echo "The sum is: $s"
ly2@DGX:~/sh$ bash until.sh
The sum is: 5050
发布了18 篇原创文章 · 获赞 0 · 访问量 1737

猜你喜欢

转载自blog.csdn.net/weixin_44159487/article/details/103216548
今日推荐