1.在shell脚本中的各种条件结构和流程控制都要进行各种的测试,然后根据测试的结果执行不同的操作,有时也会和if语句结合,来完成测试判断,以减少程序的运行错误。
也就是说,当我们在写一个脚本,里面没有任何的判断,就写了一些很普通的命令,那么在我们运行脚本的时候,当遇到了错误,也会一直的执行下去,这样就导致了我们脚本执行的结果是错误的。 这时候我们就会用到我们的条件测试比较。
那么在执行条件测试中通常会返回 “真”或者“假”就像我们执行一条成功的命令,那么执行完这条命令 我们echo$? 如果它返回的是0 那么就是真的返回的状态是非0那么就是假的 也就是错的。
那么在bash编程里要条件测试,那么就会有条件测试常用的语法形式,如下:
语法1:test <测试条件>
语法2:[<测试条件>]
语法3:[[<测试条件>]]
语法4:((<测试条件>))
注意:在语法1和语法2中的[]是一样的,语法3为扩展的test命令,语法4中的(())常用于计算
&& || >< 等操作符可以应用在[[]]中但是不可以用在[]号中 []一般用于-a –o –gt这些整数比较
但是对于数值运算我们还是用(())最好
一、test条件测试的简单实例
[root@shell-yankerp src]# test -f qq && echo "yes" || echo "no" yes [root@shell-yankerp src]#
解释:在以上命令中-f的意思代表qq是否是个普通文件,如果是那么就输出yes,否则输出no,那么在我当前路径qq却是是一个普通文件,那么就输出yes
例2:
[root@shell-yankerp ~]# mkdir /tmp/yankerp [root@shell-yankerp ~]# test -f /tmp/yankerp/ && echo "yes" || echo "no" no [root@shell-yankerp ~]#
我们创建了一个yankerp目录,它确实不是文件,它是一个目录,所以输出no
二、test空格注意:
test -f 文件名 && echo “yes” || echo “no”
在这里我用了很大的空格分开,为了方便能够看清
例1: 注意空格
那么我们把file文件给删掉再次测试
解释:如果file文件是一个普通的文件,那么输出yes否则输出no,在上图中我们都把file文件删除了,它都没有这个东西,那么肯定就是输出no了
例2:在test命令中有一个-z的选项(测试字符串长度是否为0)如下:
以上图中输出了no 因为zhangsan它不是0个字符啊 那么就肯定输出no
在这里我们用了空格,什么都没有,那么它就等于0就是对的 所以输出yes
那么我们可以使用变量来测试如下:
在这里a的变量值就是一个空白,那么就是等于0所以下面的条件就是真的
到这里我们的test基本的一些语法操作已经结束了。
三、[]中括号测试语法实例
其实在上面已经说了[]和test是一样的 自我认为[]就是test测试如下:
在-f前面和后面都是有空格的file文件的后面也要有空格 ~~~注意!!!
解释:如果file文件是一个普通文件 那么就输出yes否则输出no
练习如下:
[root@shell-yankerp src]# touch file [root@shell-yankerp src]# touch /tmp/yankerp/qq.txt [root@shell-yankerp src]# [ -f file ] && echo "yes" || echo "no" yes [root@shell-yankerp src]# [ -f /tmp/yankerp/qq.txt ] && echo "yes" || echo "no" yes [root@shell-yankerp src]# [ -f /tmp/yankerp/ ] && echo "yes" || echo "no" no [root@shell-yankerp src]#
四、[[]]条件测试实例
例1:
[root@shell-yankerp src]# touch file [root@shell-yankerp src]# [[ -f file ]] && echo "yes" || echo "no" yes [root@shell-yankerp src]#
解释:如果file是一个普通文件,那么就输出yes否则输出no,感觉是不是[]和[[]]差不多了多少啊,就多了一个[]号,其实不是这样的~
注意:在[]号中不可以用&& || ><等操作符,但是在[[]]中可以用&&|| >< 那么在[]号中只能用-a –o –gt(用于整数!)
在上面我们已经介绍了测试常用的语法,接下来介绍常用的文件测试操作符(注意是文件操作符)
-d :文件为目录文件那就是真的
-f :上面已经说了 如果文件是普通文件那么就是真的
-e : 这个其实很简单了,只要是个文件,不管他是什么文件都是真的
-r :文件存在,但是文件可以读那么就是真的
-w : 文件存在,但是文件有写入权限,那么就是真的
-x : 文件存在,则文件可以执行,那么就是真的
-s : 文件存在,并且文件大小不为0那么就是真的,-z如果文件等于0那么就是真的
-L : 文件存在且为链接文件则为真
f1 -nt f2 :文件1比文件2新那么就是真的,条件成立
f1 -ot f2 :文件1比文件2旧,那么就是真的,条件成立。这个是根据文件的修改时间来计算
以上就是常用的文件测试操作符
看到以上这些东西,不要慌张,慢慢记~~~大哭
一、文件测试表达式实例:
[root@shell-yankerp src]# [ -f file ] && echo "yes" || echo "no" #测试文件是否为普通文件 no #输出了NO [root@shell-yankerp src]# touch file #创建了一个普通文件 [root@shell-yankerp src]# [ -f file ] && echo "yes" || echo "no" #再次测试 yes #输出yes [root@shell-yankerp src]
2、目录文件实践
[root@shell-yankerp ~]# mkdir /tmp/file #创建一个file目录 [root@shell-yankerp ~]# touch /tmp/file/yankerp #在file目录下创建yankerp文件 [root@shell-yankerp ~]# [ -f /tmp/file/yankerp ] && echo "yes" || echo "no" #如果它是一个普通文件那么输出yes yes #输出结果 [root@shell-yankerp ~]# [ -d /tmp/file/yankerp ] && echo "yes" || echo "no" #如果他是一个目录 no #输出no 因为yankerp它是文件 但不是目录 [root@shell-yankerp ~]# [ -d /tmp/file/ ] && echo "yes" || echo "no" #如果file是文件而且是目录那么输出yes yes [root@shell-yankerp ~]# [ -e /tmp/file/yankerp ] && echo "yes" || echo "no"#不管你是普通文件目录只要是文件就yes yes [root@shell-yankerp ~]#
测试文件属性实例
[root@shell-yankerp src]# ll 总用量 0 -rw-r--r--. 1 root root 0 2月 2 06:48 file [root@shell-yankerp src]# [ -r file ] && echo "yes" || echo "no" yes [root@shell-yankerp src]# [ -w file ] && echo "yes" || echo "no" yes [root@shell-yankerp src]# [ -x file ] && echo "yes" || echo "no" no [root@shell-yankerp src]#
3、测试Shell变量实例
[root@shell-yankerp ~]# a=/tmp/yankerp/qq.txt [root@shell-yankerp ~]# [ -f "$a" ] && echo "yes" || echo "No" yes [root@shell-yankerp ~]# [ -d "$a" ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ -e "$a" ] && echo "yes" || echo "no" yes
4、对于单个目录或者文件进行测试
[root@shell-yankerp ~]# [ -e aaaa.sh ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -f aaaa.sh ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -d aaaa.sh ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ -r aaaa.sh ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -w aaaa.sh ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -x aaaa.sh ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ -s aaaa.sh ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# ll aaaa.sh -rw-r--r--. 1 root root 229 2月 2 09:08 aaaa.sh [root@shell-yankerp ~]#
注意:这里有一个很特殊的变量如下:
[root@shell-yankerp ~]# echo $zhangsan #echo一个变量 但是它的输出结果是空的 [root@shell-yankerp ~]# [ -f $zhangsan ] && echo "yes" || echo "no" 如果$zhangsan是一个普通文件 那就输出yes yes [root@shell-yankerp ~]#
但是我们发现$zhangsan都没有值 但是它却输出了yes…这明显是错的啊,这时候我们需要加””号 如下
[root@shell-yankerp ~]# echo $zhangsan [root@shell-yankerp ~]# [ -f "$zhangsan" ] && echo "yes" || echo "no" no [root@shell-yankerp ~]#
在真正的有变量有值加双引号和单引号时没有区别的!! 但是当变量名没有对应的值时候我们就需要加双引号
特殊条件测试表达式如下:
[ -f aaaa.sh ] && { echo "xxxxxxx" } [[ -f aaaa.sh ]] && { echo "xxxxxxx" } test -f aaaa.sh && { echo "xxxxxx" }
以上就是关于文件操作符的一些应用!!!
二、字符串测试表达式
有字符串测试表达式 那么就会有字符串操作符如下:
-n “字符串”:字符长度不是0那么就是真的
-z “字符串” : 字符长度是0那么就是真的
“串1” “=” “串2” : 字符串1等于字符串2,那么就是真的~可以使用==来代替
“串1” “!=” “串2” : 字符串1不等于字符串2 那么就就是真的,注意:不可以使用!==代替!=
例:字符串条件表达式案例
[root@shell-yankerp ~]# [ -n zhangsan ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -z zhangsan ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# var=zhangsan [root@shell-yankerp ~]# [ -n "$var" ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ -z "$var" ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ "zhangsan" == "zhangsan" ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ "zhangsan" == "lisi" ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ "zhangsan" == "$var" ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ "zhangsan" != "lisi" ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]#
剖析:
第一段 [ -n zhangsan ] && echo "yes" || echo "no" 如果zhangsan这个字符长度大于0 那么成立输出yes 否则输出no 第二段 [ -z zhangsan ] && echo "yes" || echo "no" 如果zhangsan字符等于0 那么输出yes 否则no 第三段 var=zhangsan 设置了一个变量 [ -n "$var" ] && echo "yes" || echo "no" 如果这个变量大于0那么就输出yes否则no 第四段 [ -z "$var" ] && echo "yes" || echo "no" 如果这个变量长度等于0 那么就输出yes 否则no 第五段 [ "zhangsan" == "zhangsan" ] && echo "yes" || echo "no" 如果 zhangsan 等于 zhangsan 那么就输出yes 否则no 第六段 [ "zhangsan" == "lisi" ] && echo "yes" || echo "no" 如果zhangsan 等于 lisi 那么就输出yes 否则no 第七段 [ "zhangsan" == "$var" ] && echo "yes" || echo "no" 如果zhangsan等于这个变量 这个变量的值就是张三所以是yes 第八段 [ "zhangsan" != "lisi" ] && echo "yes" || echo "no" 如果张三不等于lisi 那么就输出yes 否则no
字符串的操作符常用的就以上几种”=” “==” “!=” “-n” “-z”
三、整数二元比较操作符
在[]以及test中使用比较符号 在 (())或者[[]]中使用的符号
-eq等于 相等 ==或=
-ne 不等于 !=
-gt 大于 >
-ge 大于等于 >=
-lt 小于 <
-le 小于等于 <=
“=”和!= 也可以在[]中使用,但是><在[]中就不行了 之后会演示。如果一定要><在[]中使用的话需要用\来转义
二元数字在[]中使用><
[root@shell-yankerp ~]# [ 2 > 1 ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ 2 < 1 ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]#
我们发现第一行的结果是对的 那么第二行输出yes? 难道2<1? 所以这时候我们就要加\号
[root@shell-yankerp ~]# [ 2 \< 1 ] && echo "yes" || echo "no" no [root@shell-yankerp ~]#
二元数字在[]使用gt lt比较符号
[root@shell-yankerp ~]# [ 5 -gt 3 ] && echo "yes" || echo "no" 5大于3 yes [root@shell-yankerp ~]# [ 5 -lt 3 ] && echo "yes" || echo "no" 5小于3 no [root@shell-yankerp ~]# [ 3 -ge 3 ] && echo "yes" || echo "no" 3大于等于3 yes [root@shell-yankerp ~]# [ 3 -le 3 ] && echo "yes" || echo "no" 3小于等于3 yes [root@shell-yankerp ~]# [ 3 -ne 3 ] && echo "yes" || echo "no" 3不等于3 no [root@shell-yankerp ~]#
二元数字在[[]]使用不同的操作符比较
[root@shell-yankerp ~]# [[ 6 > 3 ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ 6 < 3 ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ 6 == 3 ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ 6 == 6 ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ 6 != 6 ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ 6 -gt 6 ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ 6 -gt 3 ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ 6 -ge 3 ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ 66 = 66 ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ 66 = 65 ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]#
自我总结:如果使用>< != || 等操作符—可以使用[[]]
如果使用gt
lt ge le ne eq 等操作符—–使用[]
如果使用>< 比较时 最好使用(())来进行比较
因为在上一次数值运算时候,数值运算符命令就包含了(())
通过整数变量测试实践
[root@shell-yankerp ~]# a=10 [root@shell-yankerp ~]# b=9 [root@shell-yankerp ~]# [ $a -gt $b ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ $a -ge $b ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [ $a -lt $b ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ $a -le $b ] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [ $a -eq $b ] && echo "yes" || echo "no" no
通过变量[[]]实践
[root@shell-yankerp ~]# a=50 [root@shell-yankerp ~]# b=40 [root@shell-yankerp ~]# [[ $a > $b ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ $a>=$b ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ $a < $b ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ $a=<$b ]] && echo "yes" || echo "no" no [root@shell-yankerp ~]# [[ $a != $b ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]#
到这里先来一次总结
上面介绍了条件测试;条件测试语法格式为:
test [<>] [[<>]] ((<>))
文件的操作符包括:-d -f -e -w -r -x -z -s 等
字符串操作符包括:-n -z = !=或者==
数值操作符[]包括:gt ge lt le eq ne 等;
数值操作符[[]]包括:>< =< >= != 等;
ok接下来开始逻辑操作符
在 [] test中使用的操作符 在 [[]]中使用的操作符
-a && and 与 两端都为真
-o
|| or 或者 两端有一个为真
! ! 取反
例1:
[root@shell-yankerp ~]# [ -f aaaa.sh -a anaconda-ks.cfg ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ -f aaaa.sh && anaconda-ks.cfg ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]#
如果aaaa.sh与anaconda-ks.cfg是一个普通文件 那么就输出yes否则输出no
在这里我们使用了[] [[]]两个不同的格式,也就是说,如果aaaa.sh 和anaconda-ks.cfg这两个文件 只要一个不是普通文件 那么就是假,如下:
[root@shell-yankerp ~]# rm -rf aaaa.sh [root@shell-yankerp ~]# [ -f aaaa.sh -a anaconda-ks.cfg ] && echo "yes" || echo "no" no [root@shell-yankerp ~]#
在上面这条命令我已经把aaaa删除掉了 它肯定不是文件了 但是anaconda-ks.cfg它是一个普通文件 但是上面说了 如果有一个错误 那么就是假的,所以输出结果为no
这就是 [-a] 和 [[&&]] 的作用
例2:我们使用|| 和 -o也就是或者的意思
[root@shell-yankerp ~]# rm -rf aaaa.sh [root@shell-yankerp ~]# [ -f aaaa.sh -o anaconda-ks.cfg ] && echo "yes" || echo "no" yes [root@shell-yankerp ~]# [[ -f aaaa.sh || anaconda-ks.cfg ]] && echo "yes" || echo "no" yes [root@shell-yankerp ~]#
以上的意思是,如果aaaa.sh或者anaconda-ks.cfg其中有一个文件是普通文件,那么就是真的 ;注意:这里的或者在[[]]中用 && 表示,那么在[]括号中就用-o 来表示。 注意:这和上面的 -a 和 && 是不一样的!!!
例3变量的实践
[root@shell-yankerp ~]# a=/etc/services [root@shell-yankerp ~]# b=/tmp/file/ [root@shell-yankerp ~]# [ -f $a -a -f $b ] && echo yes || echo no no [root@shell-yankerp ~]# [ -f $a -o -f $b ] && echo yes || echo no yes [root@shell-yankerp ~]#
在这里我把a做为变量 值为/etc/services这个文件 b的值为/tmp/file这个目录
那么-f 如果a这个变量和b是一个普通的文件,那么输出yes但是这个输出的no 因为我们B的变量值它不是文件啊 它是一个目录 不是普通文件 那么这里就用到了-o 来判断 只要一个是普通文件那么就为真
我们使用[[]]来进行测试如下:
[root@shell-yankerp ~]# [[ -f $a && -f $b ]] && echo yes || echo no no [root@shell-yankerp ~]# [[ -f $a || -f $b ]] && echo yes || echo no yes [root@shell-yankerp ~]#
我们发现其实都是一样的 只不过不同的操作符对应的不同的方式而已!!!
到这里其实书上有很多的实践都挺不错的,但是我想按照我的想法来概括以上大部分的东西 大致的一个脚本如下:
#!/bin/bash # This is a yankerp # cat <<yankerp +------------------------------------------------+ | | | ====================== | | 一键安装服务 | | by Yankerp | | ====================== | | 1. 安装Nginx | | 2. 安装Apache | | 3. 安装MySQL | | 4. 安装PHP | | 5. 部署LNMP环境 | | 6. 安装zabbix监控 | | 7. 退出此管理程序 | | 8. 关闭计算机 | | | +------------------------------------------------+ yankerp read -p "请您输入1-8随意的数值:" a [[ $a == 7 ]] && { exit 7 } expr $a + 1 &>/dev/null [ $? -ne 0 ] && { echo "/bin/bash $0 请您输入数值" exit 1 } (( $a > 8 )) && { echo "/bin/bash $0 请您输入比8小的数字" exit 1 } [ $a -eq 0 ] && { echo "/bin/bash $0 请您输入1-8的数字!" exit 1 } if [ $a -eq 1 ] then echo "开始安装Nginx咯" elif [[ $a == 2 ]] then echo "开始安装Apache" elif (( $a == 3 )) then echo "安装MySQL..." elif (( $a == 4 )) then echo "安装PHP" fi if [ $a -eq 8 ] then `shutdown -h now` fi
在这里我会一条条的解释:
cat <<yankerp +------------------------------------------------+ | | | ====================== | | 一键安装服务 | | by Yankerp | | ====================== | | 1. 安装Nginx | | 2. 安装Apache | | 3. 安装MySQL | | 4. 安装PHP | | 5. 部署LNMP环境 | | 6. 安装zabbix监控 | | 7. 退出此管理程序 | | 8. 关闭计算机 | | | +------------------------------------------------+ yankerp
以上的这段表示 在我们的交互式界面中展示,那么也就是输出以上的一个表格菜单!!效果如下:
这时候我们要想一件事情,输出来这个表格肯定是要让用户去选择安装什么服务吧? 如下:
read -p "请您输入1-8随意的数值:" a
那么这一行完全可以理解为,等待用户输入一个内容 并且把这个内容赋值给a这个变量,输出的效果如下:
它会一直等待用户输入内容,那么接下来该用户输入了,那么如果用户想直接退出此脚本,那么应该输入7这个数值所以,以下的命令可以实现如下:
[[ $a == 7 ]] && { exit 7 }
意思是说 当用户输入7 那么7这个数值就会赋值给a这个变量 以上是一个判断 如果a这个变量为7 那么就执行exit退出脚本
2.但是有时候用户会有点跳,它有可能会输入字符串,那该如何解决这个问题,如下:
expr $a + 1 &>/dev/null [ $? -ne 0 ] && { echo "/bin/bash $0 请您输入数值" exit 1 }
解释:现在用户已经输入了内容赋值给了变量a,如果用户输入的是字母,那么下面我们就可以使用expr数值运算命令来解决这个问题,$a + 1 这个结果输出到/dev/null 不显示,下面进行判断了 如果用户输入的是数值那么就是0的状态码,如果用户输入的是字符串 那么就是非0 但是以上我们设置了判断说,如果以上命令执行的结果不是0那么就退出此脚本,那我们来测试一下。
好 那么接下来 在想一个问题,有可能用户看到1-8了 它想输入个9 那这该怎么解决? 如下:
(( $a > 8 )) && { echo "/bin/bash $0 请您输入比8小的数字" exit 1 }
这时候我们就会用到本章所说的 >号 意思说 如果用户输入的数字比8大 那么我们输出一条 请您输入比8小的数字随后退出脚本
随后用户有可能还会想着,哦?比8小? 那我输入个0呗~~ ….. 解决方法如下:
[ $a -eq 0 ] && { echo "/bin/bash $0 请您输入1-8的数字!" exit 1 }
以此类推如果用户输入0 那么我们继续输出请您输入1-8的数字
到这里:我们对用户输入的不是数值已经解决了,对用户输入的数值大于8 或者是0我们也解决了,那么接下来我们该执行相应的操作了如下:
if [ $a -eq 1 ] then echo "开始安装Nginx咯" elif [[ $a == 2 ]] then echo "开始安装Apache" elif (( $a == 3 )) then echo "安装MySQL..." elif (( $a == 4 )) then echo "安装PHP" fi if [ $a -eq 8 ] then `shutdown -h now` fi
在以上的操作用到了 [] [[]] (()) 也概括了上面的一些条件判断的一些语法,那么最后的结果如下: