Linux Shell之五 流程控制--选择

    流程控制可根据不同的情况做不同的处理,而且可重复执行指定的程序区域,展现程序的生产力。在Bash Shell中,流程控制可以分为两大类:

“选择”和“循环”;

1、选择:if、case、select

2、循环:for、while、until、select

命令select既属选择也属于循环。

一、命令的结束状态

在Shell中每一个命令执行后,都会传回一个结束状态值,只分两种,如果成功,传回0,失败则传回非0.

当命令执行后,用$?来查看状态返回值,当在Shell进行条件测试的时候$?=0为真,$?=非0为假。

[root@Shell ~]# pwd
/root
[root@Shell ~]# echo $?
0
[root@Shell ~]# pwdddd
-bash: pwdddd: command not found
[root@Shell ~]# echo $?
127

当一个命令正常执行的时候,$?=0.当一个命令输入错误的时候,$?=非0

比如yum安装软件、复制文件、删除文件、判断文件是否存在等..如果正确执行,则$?=0,如果中间出错,$?=非0


二、if条件判断

if 条件测试;then

命令区域

fi

如果"条件测试"为真,就执行"命令区域"的指令,否则继续fi下一行指令。

[root@Shell ~]# cat test.sh 
#!/bin/bash
#
if grep -q ^root /etc/passwd;then
echo "The user root is exist"
fi
[root@Shell ~]# bash test.sh 
The user root is exist

使用grep在/etc/passwd搜索以root开头的关键词,如果为真,就继续执行下边的命令(grep -q表示只判断真假,不作输出)。

最简单的if语法:if-then-else

if 条件测试;then

命令区域1

else

命令区域2

fi

如果"条件测试"为真,就执行"命令区域1"的指令,否则就执行"命令区域2"的指令。

[root@Shell ~]# cat test.sh 
#!/bin/bash
#
if grep -q ^roothi /etc/passwd;then
echo "The user roothi is exist"
else
echo "The user roothi not exist"
fi
[root@Shell ~]# bash test.sh 
The user roothi not exist

判断用户roothi是否存在。

if的完整语法

if  条件测试1;then

 命令区域1

elif  条件测试2;then

 命令区域2

else  

 命令区域3

fi

如果条件测试1为真,则执行命令区域1,如果为假,则执行条件测试2;如果条件测试2为真,则执行命令区域2,如果条件测试2为假,则执行命令区域3(elif条件可以有多个)。

[root@Shell ~]# ./test.sh 5 2
5 is the bigger!
[root@Shell ~]# ./test.sh 5 10
10 is the bigger!
[root@Shell ~]# ./test.sh 5 5
5 = 5 
[root@Shell ~]# cat test.sh 
#!/bin/bash
#
declare -i a b   #声明a b都在正整数
a=$1
b=$2
if (( $a > $b ));then
echo $a is the bigger!
elif (( $a < $b ));then
echo $b is the bigger!
else
echo "$a = $b "
fi


三、条件测试的写法

条件测试的写法有10种。(传回结果0为真值,非0为假值)

1、执行某一个命令的结果。

   if grep -q "root" /etc/passwd;then (-q 静默,只为判断$?)

      echo "root is exist"

其结束状态为最后一个命令执行的结果

2、传回某一命令结果的相反值。

   ! 命令(中间要用空格隔开)

   if ! grep -q "root" /etc/passwd;then (-q 静默,只为判断$?)

      echo "root is not exist"

如果命令传回结果为0,则加上!之后传回值为1;反之如果命令传回值为非0,则加上!之后传回值为0

3、使用复合命令((算式))

   运算结果不为0为真,为0为假

   ((8*3)) 24 真

   ((5-5)) 0  假

   ((20<30))  真 

   ((20>30))  假

   ((20&&30)) 真

   ((20&&0))  假   

4、使用Bash关键字‘[[  ]]‘组成的句子:[[ 判断式 ]]

   [[ 后和 ]]前至少有一个空格 

   if [[ str > xyz ]];then

      echo "字符串str比较大"

5、使用内置命令:test判断式

   if test "str" \> "xyz";then                     (>为特殊字符,用\转义)

      echo "字符串str比较大"

6、使用内置命令:[ ]判断式

   [] 与test用法相同

   if [ "str" \> "xyz" ];then                     (>为特殊字符,用\转义)

      echo "字符串str比较大"  

7、使用-a、-o进行逻辑组合

   [ -r filename -a -x filename] 如果filename可读且可执行,则为真。-a,且。

   [ -r filename -o -x filename] 如果filename可读或可执行,则为真。-o,或。

8、命令1&&命令2

   命令1真才执行命令2,都真传回值0,否则1

  if grep -q "root" /etc/passwd && ((8<10));then

9、命令1||命令2

   命令1假才执行命令2,如果一个命令或都为真传回值0,否则1

   ((2<3))||((4<5));then  

10、$$和||合用

   如果是 “[ 判断式 ] &&指令1||指令2”形式,视为 if-then-else 

   [ "2" \> "1" ]&& echo "right"||echo "error"等同于等同于以下脚本:

   if [ "2" \> "1" ];then

     echo "right"

  else

     echo "error"

   fi

总结:

[[ ]]、test、[]用法意思相近,但[[ ]]更自由(不必担心特殊符号,不必转义),(())也不受特殊符号影响。

在[[判断式]]中,如果使用==或!=且右方的字符串没有使用单引号、双引号,则视为对比该字符串形成的“样式”,如果相符,传回0,否则1。

!/bin/bash

a="str"

if [[ $a == ??? ]];then    意思是:用$a的值,对比样式???(3个字符串) 

  echo "hello"

fi

上边如果把if行改为 

if [[ $a == "???" ]];then  意思是:用$a和字符串???是否相等 


四、条件判断式的真假值

判断式:影响程序流程的式子,判断式分为“单元”和“二元”

如  -f filename ,测试文件是否存在。-f后跟一个操作数的文件称为“单元”。

如 参数1 -gt 参数2,测试参数1值是否大于参数2,-gt左右各接一个要比较的参数,这种判断式称为“二元”。

--------------------关于文件的判断式--------------------

判断式                  什么情况下为真

-a/e 文件存在

-b   文件存在,且文件是区域设备文件

-c   文件存在,且文件是字符设备文件

-d   文件存在,且文件是目录

-p   文件存在,且该文件是管道文件(FIFO)

-f   文件存在,且该文件是一般文件

-g   文件存在,且该文件设立了 set group id属性 -u uid

-h/L 文件存在,且该文件是符号链接文件

-r   文件存在,且该文件有可读取的属性 -w 可写 -x 可执行

-s   文件存在,且该文件大小大于0(文件存在,且文件有数据)

-t   文件描述符   如果文件描述符是开启的,且链接了某一个终端

-S   文件存在,且该文件是socket文件

-N   文件存在,且该文件从上次读取后,曾修改过。

文件1  -nt 文件2   如果文件1比文件2新;文件1存在,但文件2不存在。

文件1  -ot 文件2   如果文件1比文件2旧;文件1不存在,但文件2存在。

文件1  -ef 文件2   如果文件1和文件2 参考到相同的设备和inode编号。

--------------------关于字符串的条件判断式--------------

判断式                        什么情况下为真

-z 长度为0(即空字符串)

-n 长度不为0(即非空字符串)

字符串字符串长度不为0

==和=代表相同(左右两边分别有个字符串)

!= 不等  < 小于  > 大于 (如果<>出现在[]或test中的时候,要用\转义)

--------------------关于算式的条件判断式----------------

-eq   相等

-ne   不相等

-lt   小于

-le   小于或等于

-gt   大于

-ge   大于或等于

-------------------关于Bash选项的条件判断式-------------------

-o   set选项的名称 如果该选项为开启状态则为真。

!/bin/bash

set -o

if [ -o history ];then

  echo ‘Bash选项history开启‘

else

  echo ‘Bash选项history关闭‘

fi


五、case条件判断

if条件判断中提到的if条件判断,一旦要进行的条件测试的情况多了起来,if和elif的语法就会变得很冗长,case条件判断语法可补其不足。

------------------case的语法结构------------------

case 待测项 in

   样式串行1 )命令区域1;;

   样式串行2 )命令区域2;;

   样式串行3 )命令区域3;;

   .....

   *) 命令区域;;

esca

样式串行可以是字符串:如a、b、mary

              通配符:*任意长度(包括空字符)  ?一个字符

              字符集合:[a-d]mm,表示amm、bmm、cmm、dmm

              分隔符:|             

如果待测项与样式串行符合的话,case会执行该样式后的命令区域,命令区域可以是单一指令或多行指令,最后以;;结束。

样式串行可以用字符串和通配符组成,默认会区别大小写。

如果串行有好几个字符要对比,用|隔开,|有或的意思(只要符合其中之一就算成功)。

样式串行可以写为‘(样式串行)‘或‘样式串行‘

*)通常放在case最后的一个区域,用来谱捉不符合指定样式的其它情况。

例子:

!/bin/bash

name=$1                                      第一个输入的参数附给name 

case $name in

  a|b|c)                                      匹配的选项1,变量为a或b或c的时候

     echo "hello,abc group"                   输出结果1

    ;;                                        ;;可放到输出结果1后,也可另起一行

  huan)                                       匹配选项2 ,变量为huan的时候

     echo "i love you"                        输出结果2

    ;;

  s*)                                         匹配选项3,变量以s开头的字符串

    echo "you are first s"                    输出结果3

    ;;

  *)                                          匹配选项4 不符合上边任何条件的字符串

    echo "what is this?";;                输出结果4 "what is this?".......    

esca      结束

-----------------高级样式--------------------

样式    符合情况

?(样式串行) 符合0个或1个

*(样式串行) 符合0个以上

+(样式串行) 符合1个以上

@(样式串行) 符合其中1个

!(样式串行) 只要不是出现在括号里的样式就算符合      

j@(ac|xy|pq)k|join|joe echo ‘hello‘;;

只要变量符合jack、jxyk、jpqk、join、joe其中之一就算符合

if [[ $cmd == @(a|b) ]];then 

只要是a或b就算是对比成功。

本文出自 “Welcome To Linux World” 博客,请务必保留此出处http://linuxnote.blog.51cto.com/9876511/1641204

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。