流程控制可根据不同的情况做不同的处理,而且可重复执行指定的程序区域,展现程序的生产力。在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
原文地址:http://linuxnote.blog.51cto.com/9876511/1641204