流程控制 Shell 编写的程序是顺序执行的,也就是说第一命令先执行,然后接着执行第二条命令,然后再下一条,以此类推,而流程控制就是改变上面这种顺序执行的方式。
流程控制语句用于控制程序的流程,以实现程序的各种结构方式,即用来实现对程序流程的选择、循环、转向和返回等进行控制。
流程语句中需要依赖到条件表达式,也就是 [test 测试命令](/2022/11/10/Shell 中的 test 测试命令/)。
Shell 中的流程控制语句和其他编程语言的流程语句大体相同,分为:
if 条件判断语句
case 条件判断语句
for 循环语句
while 循环语句
until 循环语句
特殊流程控制语句
条件判断语句 if 条件语句分为单分支语句和多分支语句。
单分支if条件语句 单分支条件语句最为简单,就是只有一个判断条件,如果符合条件则执行某个程序,否则什么事情也不做。
语法如下:
1 2 3 if [ 条件判断表达式 ];then 程序fi
if语句使用fi结尾,和其他编程语言使用大括号结尾不同。
[ 条件表达式 ] 就是使用 [test](/2022/11/10/Shell 中的 test 测试命令/) 命令进行判断,在test命令中,使用 [] 来简写test命令的花,中括号和条件表达式之间必须有空格。
then 后面跟着符合条件之后执行的程序,可以放在 [] 之后,用 ; 分割;也可以换行写入,这样就不需要 ; 了。示例:
1 2 3 4 if [ 条件表达式 ] then 程序fi
示例,如果根分区的使用率大于等于 80% 时则报警。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [root@cjh tmp]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 19G 2.1G 16G 12% / tmpfs 491M 0 491M 0% /dev/shm /dev/sda1 240M 34M 194M 15% /boot [root@cjh tmp]# df -h | grep /dev/sda3 /dev/sda3 19G 2.1G 16G 12% / [root@cjh tmp]# df -h | grep /dev/sda3 | awk '{print $5}' 12% [root@cjh tmp]# df -h | grep /dev/sda3 | awk '{print $5}' | cut -d "%" -f 1 12 [root@cjh tmp]# vim if1.sh rate=$( df -h | grep /dev/sda3 | awk '{print $5}' | cut -d "%" -f 1 )if [ $rate -ge 10 ] then echo "Warning! /dev/sda3 is full !!!" fi [root@cjh tmp]# chmod 755 if1.sh [root@cjh tmp]# ./if1.sh Warning! /dev/sda3 is full !!!
双分支if条件语句 语法格式:
1 2 3 4 5 6 if [ 条件表达式 ] then 条件成立时 else 条件不成立时fi
多分支if条件语句 语法格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if [ 条件表达式1 ] then 条件表达式1成立时elif [ 条件表达式2 ] then 条件表达式2成立时elif [ 条件表达式3 ] then 条件表达式3成立时 ...更多条件else 当所有条件都不成立时fi
示例:
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 28 29 30 31 [root@cjh tmp]# vim if.shread -t 30 -p "please input number:" numberif [ $((number)) -eq 5 ] then echo "input number equls 5" elif [ "$number " -lt 5 ] then echo "input number lt 5" else echo "input number ge 5" fi [root@cjh tmp]# chmod +x if.sh [root@cjh tmp]# ./if.sh please input number:1 input number lt 5 [root@cjh tmp]# ./if.sh please input number:5 input number equls 5 [root@cjh tmp]# ./if.sh please input number:9 input number ge 5
多分支case语句 case 语句和 if-else 语句都是多分支条件语句,不过和if-else语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
语法格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 case $变量名 in "值1" ) 如果变量的值等于值1,则执行程序1 ;; "值2" ) 如果变量的值等于值2,则执行程序2 ;; …省略其他分支… *) 如果变量的值都不是以上的值,则执行此程序 ;;esac (注:case 的反写)
那case语句和if-else语句有什么区别?
case语句只能判断一个条件,是否符合某一种情况,是一种判断
而if-else语句有多个分支语句,可以判断一个输入是否唯恐,是否是文件,是否是目录等多种条件关系,是不同的判断。
在 case 语句中,会取出变量中的值,然后与语句体中的值逐一比较;如果数值符合,则执行对应的程序,如果数值不符合,则依次比较下一个值;
如果所有的值都不符合,则会执行 *) 下的程序,*) 代表所有其他值;
case 语句 以 case 开头,以 esac 结尾,是 case 的反写;
每一个分支程序之后都要通过 ;; 双分号结尾,代表该程序段结束。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #!/bin/bash echo "want to beijing,please input 1." echo "want to shanghai,please input 2." echo "want to chendu,please input 3." read -t 30 -p "please input your choice: " chocase $cho in "1" ) echo "to beijin" ;; "2" ) echo "to shanghai" ;; "3" ) echo "to chendu" ;; *) echo "error input" ;;esac
循环语句 在Shell中,循环语句有for、while和until
for for循环是固定循环,也就是在循环时就已经知道需要进行几次的循环,有时候也会把for循环称为计数循环。
for循环的语法格式有2种:
1 2 3 4 5 6 7 8 9 10 11 for 变量 in 值1 值2 值3 … do 程序 done for ((初始值;循环控制条件;变量变化)) do 程序 done
语法1中的for循环次数,取决于in后面值的个数(空格分隔),有几个值就循环几次,并且每次循环都把该值赋予给变量。也就是说,假设in后面有三个值,for循环会循环三次,第一次循环把值1赋值给变量,第二次循环会把值2赋值给变量,第三次循环会把值3赋值给变量,以此类推。
语法2与其他编程语言的for循环一致。
语法1示例:
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 [root@cjh tmp]# vim for.shfor i in 1 2 3 4 5 6 7 do if [ "$i " -eq 7 ] then echo "今天是周日" elif [ "$i " -eq 6 ] then echo "今天是周六" else echo "今天是周" $i fi done [root@cjh tmp]# chmod +x for3.sh [root@cjh tmp]# ./for.sh 今天是周1 今天是周2 今天是周3 今天是周4 今天是周5 今天是周六 今天是周日
有时候不能像示例中能到所有值,一般都是个变量,那变量该如何用到for循环里面呢?答案是可以的,示例:
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 28 29 [root@cjh tmp]# vim for2.shls >> count.log count=0for i in $(cat count.log)do count=$(($count +1 )) echo "文件名:$i ,count:$count " done [root@cjh tmp]# chmod +x for3.sh [root@cjh tmp]# ./for2.sh 文件名:count.log,count:1 文件名:Desktop,count:2 文件名:Documents,count:3 文件名:Downloads,count:4 文件名:for2.sh,count:5 文件名:for.sh,count:6 文件名:go,count:7 文件名:Library,count:8 文件名:Music,count:9 文件名:note,count:10 文件名:Pictures,count:11 文件名:project,count:12 文件名:software,count:13 文件名:Videos,count:14
语法2示例:
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 28 [root@cjh tmp]# vim for3.sh count=$(ls | wc -l)for ((i=1 ;i<="$count ";i=i+1 ))do echo "i:$i " done [root@cjh tmp]# chmod +x for3.sh [root@cjh tmp]# ./for3.sh i:1 i:2 i:3 i:4 i:5 i:6 i:7 i:8 i:9 i:10 i:11 i:12 i:13 i:14
while 对while循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。和for循环的第二种格式for(初始值;循环控制条件;变量变化)类似。
语法格式:
1 2 3 4 while [ 条件判断式 ] do 程序 done
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/bin/bash i=1sum =0while [ $i -le 100 ] do sum =$(( $sum +$i )) i=$(( $i +1 )) done echo "The sum is:$sum "
until unti1循环和whi1e循环相反,unti1循环时只要条件判断式不成立侧进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
语法格式:
1 2 3 4 until [ 条件判断式 ] do 程序 done
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/bin/bash i=1sum =0until [ $i -gt 100 ] do sum =$(( $sum +$i )) i=$(( $i +1 )) done echo "The sum is:$sum "
特殊流程控制语句 除了if…else、case、for、while、until这5种流程控制语句外,还有一些特殊的流程控制语句。
比如:exit语句、break语句、continue语句。
exit
系统有一个exit语句,用于退出当前用户的登录状态;或者是退出当前终端。
可是在Shell脚本中,exit语句是用来退出当前脚本的。也就是说,在Shell脚本当中,只要碰到了exit语句,后续的程序就不会再执行,而是直接退出脚本。
语法格式:
后面的breank语句和continue语句与其他编程语言的相同,不再赘述。