流程控制
Shell 编写的程序是顺序执行的,也就是说第一命令先执行,然后接着执行第二条命令,然后再下一条,以此类推,而流程控制就是改变上面这种顺序执行的方式。
流程控制语句用于控制程序的流程,以实现程序的各种结构方式,即用来实现对程序流程的选择、循环、转向和返回等进行控制。
流程语句中需要依赖到条件表达式,也就是 [[Shell 中的 test 测试命令|test 测试命令]]。
Shell 中的流程控制语句和其他编程语言的流程语句大体相同,分为:
- if 条件判断语句
- case 条件判断语句
- for 循环语句
- while 循环语句
- until 循环语句
- 特殊流程控制语句
条件判断语句
if 条件语句分为单分支语句和多分支语句。
单分支if条件语句
单分支条件语句最为简单,就是只有一个判断条件,如果符合条件则执行某个程序,否则什么事情也不做。
语法如下:
1 2 3
| if[ 条件判断表达式 ];then 程序 fi
|
if语句使用fi结尾,和其他编程语言使用大括号结尾不同。
[ 条件表达式 ]
就是使用 [[Shell 中的 test 测试命令|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] 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] /dev/sda3 19G 2.1G 16G 12% /
[root@cjh tmp] 12%
[root@cjh tmp] 12
[root@cjh tmp]
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] [root@cjh tmp] 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]
read -t 30 -p "please input number:" number
if [ $((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]
[root@cjh tmp] please input number:1 input number lt 5
[root@cjh tmp] please input number:5 input number equls 5
[root@cjh tmp] 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: " cho
case $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]
for 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] [root@cjh tmp] 今天是周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]
ls >> count.log count=0
for i in $(cat count.log) do count=$(($count+1)) echo "文件名:$i,count:$count" done
[root@cjh tmp] [root@cjh tmp] 文件名: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]
count=$(ls | wc -l)
for((i=1;i<="$count";i=i+1)) do echo "i:$i" done
[root@cjh tmp] [root@cjh tmp] 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=1
sum=0
while [ $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=1
sum=0
until [ $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语句与其他编程语言的相同,不再赘述。