Linux shell脚本 流程控制

shell脚本的流程分为三种,顺序执行,选择执行和循环执行。顺序执行就是按照脚本中语句的顺序依次执行各条语句,每一个回车和“;”都代表了下一条命令,而选择执行是通过选择语句来对命令进行有选择的定向执行,循环执行是在特定的条件下重复执行命令。这三种执行流程在使用时可以灵活的套嵌,来满足我们的需求

一.顺序执行

顺序执行是一个大的框架,脚本里的所有命令都可以看做是在顺序执行中嵌套其他的流程

例如

#!/bin/bash

sum=0

while [ $# -gt 0 ];do

        sum=$[$(cat $1 | wc -l) + $sum]

        shift

done

echo $sum

 

上面的代码执行顺序是

  1. sum=0
  2. while到倒数第二行的done
  3. echo $sum

其中上面的第二部分while是循环执行的语句,从while到done可以看做一个整体。这就是一个顺序嵌套循环,在while语句看做一个整体的前提下,命令按照从上到下的顺序依次执行也就是顺序执行。

 

二.选择执行(if/case)

1.if

if是选择执行语句的一种,其格式为:

 

1 if 判断条件 ;then

2 判断条件为真时要执行的命令

3 elif 判断条件 ;then

4 判断条件为真时要执行的命令

5 else

6 当以上所有判断都为假时要执行的命令

7 fi

 

解释:

第一行的“if”告诉计算机,我的if语句开始了,“判断条件”告诉计算机什么情况下要执行下面的命令,“;”告诉计算机我的判断条件结束了,“then”告诉计算机接下来该执行命令了,“;then”也可以理解为固定格式。

第二行就是第一行告诉计算机要执行的命令

第三行的“elif”就是else if的意思,意思是如果第一行“if”的判断为假,则继续判断之后“elif”的判断条件

第四行是“elif”判断为真时要执行的命令

第五行的意思是当上面所有的判断都为假的时候则执行下面的命令

第六行要写所有的判断都为假的时候执行的命令

第七行告诉计算机我要结束我的if语句了

 

if语句的格式中第三四行可以根据需求写无数次,第一二七行必须写而且只能写一次,第五六行最多有一次不过可以不写,当if语句中有多个elif时,计算机会逐条对判断条件金星判断,并执行第一次为真的判断条件的命令,如果都为假,有else则执行else后的命令,五else则直接跳出if语句

例如

#!/bin/bash

a=$1

if [ $a -eq 1 ];then

        echo h

elif [ $a -eq 2 ];then

        echo i

elif [ $a -eq 3 ];then

        echo j

elif [ $a -eq 4 ];then

        echo k

else

        echo F

fi

 

解释:

在这个脚本中我把a赋值为输入的第一个参数,并依此进行判断,如果a和1相等则输出h,如果a和2相等则输出i,如果a和3相等则输出j,如果a和4相等则输出k,如果a和1,2,3,4,都不相等则输出F

 

 2.case

case是另一中选择执行语句,其格式为:

  1. case 变量 in
  2. 判断值) 执行的命令;;

       3. 判断值) 执行的命令;;

       4. *)执行的命令;;

       5. esac

 

解释:

第一行的case告诉计算机我的case语句开始了“变量”是我们要判断的数据可以是数数值也可以是字符串等等,“in”可以理解为固定格式

第二行的判断值是我们判断的依据,“)”是固定格式,告诉计算机我的判断值结束了,后面是这个判断值对应的命令“;;”告诉计算机我的执行命令到此结束,这整个一行的意思是,如果第一行的变量和我的判断值相等则执行后面的命令

第三行同第二行

第四行*代表所有的值,由于case语句是按顺序依次判断的,所以写在最后的*)意思就是上面的判断值和变量都不相等时执行之后的命令

第五行告诉计算机我的case语句结束了

 

case是按照从上至下的顺序依次判断,可根据需求将“判断值) 执行的命令;;”写任意条,而判断则会遍历这些直到遇到变量和判断值相等,执行命令并退出case,“*)执行的命令”可根据需要不写,效果是如果上面的判断值和变量都不相等则什么都不执行直接退出case

 

举例:

#!/bin/bash

case $1 in

        man)echo "男人";;

        woman)echo "女人";;

        [1-9])echo "数字";;

        [[:alpha:]])echo "字母";;

        *)echo "fault";;

esac

 

解释:

这个脚本中我把输入的第一个参数当作变量,并依次和下面的判断值作比较,当输入值为man时输出“男人”当输入值为woman时输出为“女人”当输入为数字时输出为“数字”,当输入为字母时输出为“字母”,当输入不是上面的这些情况时输出为“fault”

三.循环执行(for/while)

1.for

for循环格式:

1.for 变量 in 列表 ;do

2. 循环体

3. done

运行机制:

依次将列表中的元素赋值给变量,每赋值一次执行一次循环体,直到列表的元素用尽,循环结束

解释:

第一行的“for”告诉计算机我的for循环语句开始了,“变量”是设置的一个参数用于循环,也可以在循环体中使用,“in 列表”告诉计算机我要用于循环的元素列表,“do”告诉计算机接下来是循环体也就是要执行的命令

第二行的“循环体”也就是我们要执行的命令

第三行的“done”告诉计算机循环体结束,进行下一次循环,如果没有元素了则退出for循环

for循环中列表的书写方式:

(1) 直接给出列表 a b c

(2) 整数列表:

(a) {start..end} {1..10}

(b) $(seq [start [step]] end) $(seq 10)

(3) 返回列表的命令

$(COMMAND)

(4) 使用glob,如:*.sh

(5) 变量引用;

$@, $*

举例:

#!/bin/bash

for n in $(seq 10);do

        echo $n

done

 

解释:

这个脚本效果是输出1到10,每一次循环,都会按顺序从列表“$(seq 10)”中读取一个值赋给n,并执行echo命令,所以在每一次循环中n的值都不一样,所以每次输出的值也就不一样。

 另外for循环也可以写成c语言的形式,其格式为:

for ((i=0;i<b;i++));do

循环体

done

其中i是我们的循环变量,i=0是把i的初始值设为0,i<b,b是我们设置的一个数值,用来告诉循环什么时候停止,i++的意思是每次循环i自加1

2.while

while循环格式

  1. while CONDITION  ;do
  2. 循环体
  3. done

运行机制:

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件

“true”,则执行一次循环;直到条件测试状态为“false”终止循环

因此CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正

解释:

第一行“while”告诉计算机while循环开始,“CONDITION”是循环控制条件,控制循环,告诉计算机什么时候结束,“do”开始执行循环体

第二行“循环体”也就是我们要执行的命令

第三行“done”执行循环体结束并进入下一次循环,如果达到控制条件则退出循环

举例:

 

#!/bin/bash

n=1

while [ $n -le 5 ];do

        echo $n

        let n++

done

 

解释:

这个脚本效果是输出1到5,我先赋值n为1,在while循环中,控制条件是“[ $n -le 5 ]”意思是n小于等于5,所以第一行的意思是当n小于等于5的时候执行下面的循环体,循环体是输出n的值,“let n++”的意思是让n自加1,也就是每循环依次n就会加1,它和控制条件配合来限制循环次数

 

3.循环控制语句(continue/break/shift)

1)continue

continue[N] 用于循环体中意思是结束第N层循环,直接进入下一轮的判断,N默认为1

举例:

 

首先我写了一个两层for循环嵌套的脚本,最外层的会执行五次,每次执行会先输一个序号来告诉我们这是第几次的输出,然后执行内层的for循环,第二个for循环的作用是输出abc,“echo \ ”的作用是输出一个换行

#!/bin/bash

for n in {1..5};do

        echo -n $n

        for m in a b c;do

                echo -n $m

        done

        echo \

done

 

执行结果

[root@centos7 bin]# . a.sh

1abc

2abc

3abc

4abc

5abc

 

然后我们加入一个if语句,其执行的命令为continue。加入后在执行内层for循环语句的时候先判断变量m的值是否为b,如果为b则执行continue,跳出本次循环也就不会在执行if语句后的输出语句,跳出本次循环后直接进入下一个内层的for循环

#!/bin/bash

for n in {1..5};do

        echo -n $n

        for m in a b c;do

        if [ $m == b ];then

                continue

        fi

                echo -n $m

        done

        echo \

done

 

执行结果

[root@centos7 bin]# . a.sh

1ac

2ac

3ac

4ac

5ac

 

我们现在把continue后加一个2,加入后每当变量m的值为b就会跳出两层循环,也就是直接进入外层for的下一个循环,所以输出序号和a后直接进入下一个循环

#!/bin/bash

for n in {1..5};do

        echo -n $n

        for m in a b c;do

        if [ $m == b ];then

                continue 2

        fi

                echo -n $m

        done

        echo \

done

 

执行结果

[root@centos7 bin]# . a.sh

1a2a3a4a5a[root@centos7 bin]#

 

2)break

break N 用于循环体中,提前结束第N层循环,最内层为第一层

举例:

还是上面的例子,我们把continue换成break,换成break后每当变量m为b时则跳出整个内层的for循环,然后执行外层for循环的“echo \ ”之后进行下一次的外层for循环

#!/bin/bash

for n in {1..5};do

        echo -n $n

        for m in a b c;do

        if [ $m == b ];then

                break

        fi

                echo -n $m

        done

        echo \

done

 

执行结果

[root@centos7 bin]# . a.sh

1a

2a

3a

4a

5a

 

然后我们在break后加上2,使之直接跳出两层循环,当第一次变量m的值为b时跳出两层for循环也就是直接运行结束

执行结果

[root@centos7 bin]# . a.sh

1a[root@centos7 bin]#

 

3)shift

shift n 将参数列表向左移动n位,前n位已溢出则直接从列表中删除

举例

#!/bin/bash

while [ $# -gt 0 ];do

        echo $*

        shift

done

 

解释:

“$#”是传递给脚本的参数个数,“$*”是传递给脚本的全部参数,当参数个数大于0时输出所有参数并将参数左移

执行结果

[root@centos7 bin]# . a.sh a b c d e

a b c d e

b c d e

c d e

d e

e

 

posted @ 2018-08-13 17:59  白蓝的橙  阅读(692)  评论(0编辑  收藏  举报