Shell脚本——流程控制、循环和条件判断

前言

条件判断和循环是shell脚本的基础,也决定了脚本运行流程,是写shell脚本十分重要的知识准备。本篇文章将对这两大块知识点进行讲解和整理,希望对各位读者有所帮助。

一、流程控制

(一)if关键字

语法如下:

if [ 条件判断式1 ]
    then
        当条件判断式1成立时,执行程序1
    elif [ 条件判断式2 ]
        then
            当条件判断式2成立时,执行程序2
    else
    当所有条件都不成立时,最后执行此程序
fi
  • if语句使用fi结尾,和一般语言使用大括号结尾不同

  • [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格

  • then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要";"了

同样的,我们用if来做一个小案例,判断a.txt文件是否存在于当前目录,并将结果打印出来

file=/tmp/test_sh/a.txt

if [ -e $file ];then
        echo "a.txt is exist"
else
        echo "a.txt is no exit"
fi

输出结果:

a.txt is exist
(二)case关键字

case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句。不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。

语法如下:

case $变量名 in
    "值1")
        程序
    ;;
     "值2")
        程序
    ;;
     ...
    *)
        #如果变量的值都不是以上的值,则执行此程序
         程序
    ;;
esac

我们可以看一下下面这个例子:如果变量a的值为2,则输出结果

a=2
case $a in
 "1")
 echo "the value is 1"
 ;;
 "2")
 echo "the value is 2"
 ;;
 *)
 echo "the value is no in beheind"
esac

输出结果:

the value is 2

二、循环

shell语言的流程控制和大多数编程语言一致,主要依赖逻辑判断(if、case)和循环迭代(for、while、until)。下面就来介绍有关循环迭代的各个关键词语法的使用。

(一)for循环
语法一:for in
for 变量 in 值1 值2 值3…
    do
        程序
    done

我们以下面的脚本作为例子:

for time in morning afrernoon evening
 do
   echo "good $time , sir~"
 done

输出结果如下:

good morning , sir~
good afrernoon , sir~
good evening , sir~
for in的使用细节

我们可以看到,三个字符串都可以被顺利的遍历出来。但是有时候我们并不能实现知道要遍历的对象具体是什么,无法提前把字符串写到for in中,那么此时可以怎么处理呢?这个问题自然也可以用for in来解决,for in可以自动对Linux命令得到的列数据进行识别和迭代,比如下面的这个案例:

我们想要知道当前系统中所有运行java应用的pid是什么

for pid in $(ps -ef | grep java | awk '{print $2}')
 do
  echo "the pid of java application is $pid"
 done

输出结果如下,我们可以看到所有的java应用pid都打印出来了

the pid of java application is 1150
the pid of java application is 19597
the pid of java application is 20725
the pid of java application is 22763
the pid of java application is 23071
the pid of java application is 23390
the pid of java application is 24469
the pid of java application is 36322
语法二:for(( ))
for (( 初始值;循环控制条件;变量变化 ))
    do
     程序
    done    

我们也举一个例子来进行演示:打印从10一直累加到20的总和是多少?

sum=0
for((i=10;i<=15;i++))
  do
    echo "sum=$sum i=$i"
    sum=$(( $sum + $i ))
  done
echo "sum = $sum"

输出的结果如下:

sum=0 i=10
sum=10 i=11
sum=21 i=12
sum=33 i=13
sum=46 i=14
sum=60 i=15
sum = 75
语法三:for in + ${} (数组循环)

这种语法一般用于循环的对象类型是数组,for in${}结合使用

for in ${!arr[@]}
    do
        程序
    done

PS:${!数组[@]} 或者 ${!数组[*]} 可以取到数组的所有下标信息

具体的用法我们看下面的例子:

arr=(morning afrernoon evening)
for i in ${!arr[@]}
  do
    echo "good ${arr[i]}"
  done

输出结果如下:

good morning
good afrernoon
good evening
(二)while循环

当我们明确知道迭代对象为的个数或者其具体元素时,for循环一般是我们首选方案。但是有时候我们想要通过某种条件来启动和结束循环,这个使用while来进行循环会更加符合我们的需要。

while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。

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

用while来举一个例子,我们希望得到10累加到15的结果:

a=10
sum=10
while [ $a -lt 15 ]
  do
    a=$(($a+1 ))
    sum=$(($sum + $a))
    echo "a= $a ,sum = $sum"
  done

输出的结果如下:

a= 11 ,sum = 21
a= 12 ,sum = 33
a= 13 ,sum = 46
a= 14 ,sum = 60
a= 15 ,sum = 75
(三)until循环

until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

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

我们用until来得到10累加到15的结果:

a=10
sum=10
until [ $a -ge 15 ]
  do
    a=$(($a+1));
    sum=$(($a + $sum))
    echo "a = $a , sum = $sum"
  done

输出的结果如下:

a = 11 , sum = 21
a = 12 , sum = 33
a = 13 , sum = 46
a = 14 , sum = 60
a = 15 , sum = 75

三、条件判断

条件判断一般和结合流程控制来使用的,如果满足xx条件,则执行xx动作。条件判断的语法有2种:

  • 语法1:test condition
  • 语法2:[ condition ] (常用)
    (这里需要注意,使用语法2的话,condition前后需要加上空格)
(一)字符串的比较
[ -z STRING ]    如果STRING的长度为零则返回为真,即空是真
[ -n STRING ]    如果STRING的长度非零则返回为真,即非空是真
[ STRING1 ]    如果字符串不为空则返回为真,与-n类似
[ STRING1 == STRING2 ]   如果两个字符串相同则返回为真
[ STRING1 != STRING2 ]    如果字符串不相同则返回为真
[ STRING1 < STRING2 ]     如果 “STRING1”字典排序在“STRING2”前面则返回为真。 
[ STRING1 > STRING2 ]     如果 “STRING1”字典排序在“STRING2”后面则返回为真。 
(二)对文件的判断
[ -a FILE ] 如果 FILE 存在则为真。 
[ -b FILE ] 如果 FILE 存在且是一个块文件则返回为真。
[ -c FILE ] 如果 FILE 存在且是一个字符文件则返回为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。 
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
[ -g FILE ] 如果 FILE 存在且设置了SGID则返回为真。
[ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则返回为真。(该选项在一些老系统上无效)
[ -k FILE ] 如果 FILE 存在且已经设置了冒险位则返回为真。
[ -p FILE ] 如果 FILE 存并且是命令管道时返回为真。
[ -r FILE ] 如果 FILE 存在且是可读的则返回为真。
[ -s FILE ] 如果 FILE 存在且大小非0时为真则返回为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID位时返回为真。
[ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)
[ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则返回为真。
[ -G FILE ] 如果 FILE 存在且默认组为当前组则返回为真。(只检查系统默认组)
[ -L FILE ] 如果 FILE 存在且是一个符号连接则返回为真。 
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则返回为真。 
[ -S FILE ] 如果 FILE 存在且是一个套接字则返回为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则返回为真。 
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则返回为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则返回为真。

(三)数值的判断
[ INT1 -eq INT2 ]          INT1和INT2两数相等返回为真 ,=
[ INT1 -ne INT2 ]          INT1和INT2两数不等返回为真 ,<>
[ INT1 -gt INT2 ]           INT1大于INT2返回为真 ,>
[ INT1 -ge INT2 ]          INT1大于等于INT2返回为真,>=
[ INT1 -lt INT2 ]            INT1小于INT2返回为真 ,<
[ INT1 -le INT2 ]           INT1小于等于INT2返回为真,<=
(四)逻辑判断
[ ! EXPR ]       逻辑非,如果 EXPR 是false则返回为真。
[ EXPR1 -a EXPR2 ]      逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。
[ EXPR1 -o EXPR2 ]      逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。
[  ] || [  ]           用OR来合并两个条件
[  ] && [  ]        用AND来合并两个条件

你可能感兴趣的:(Shell脚本——流程控制、循环和条件判断)