「shell入门到精通」 一文带你熟悉shell脚本的各种表达式
作者:老油条IT记
公众号:老油条IT记
#前言:在shell脚本中,有各种的表达式,包括有条件测试表达式,文件表达式,字符串表达式,整数表达式,接下来我们来了解一下他们的使用方法
1.条件测试表达式
#首先来看一下条件测试语法
#条件测试语法 #说明1.test <测试表达式> test命令和后面<内容>之间至少有一个空格2.[ <测试表达式> ] 单中括号进行条件测试表达式,[]的边界和内容之间至少要有一个空格3.[[ <测试表达式> ]] 双括号,[[]]的边界和内容也是要有空格4.((<测试表达式>)) 双小括号,两端不用空格
#注意点
1、语法1中的test命令和语法2中的[]是等价的。语法3中的[[]]为扩展的test命令,语法4中的(())常用于计算
2、在[]中可以使用通配符等进行模式匹配,这是其区别其他集中语法格式的地方
3、&&、||、>、<等操作符可以应用于[[]]中,但不能应用于[]中,在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数)代替上述操作符
4、对于整数的关系运算,也可以使用shell的算术运算符(())
#详解
#1.1.test条件测试的语法和使用
#查看帮助:man test
#介绍:test - check file types and compare values(检查文件类型和比较值)
#语法格式:test <测试表达式>
#test的帮助文档
[root@shell ~]# man test > 1.txt
[root@shell ~]# cat 1.txt
#使用
#例一:判断如果file文件存在且为一个文件,就输出true,否则输出false
[root@shell ~]# test -f file && echo true || echo false
false
#讲解:因为file这个文件不存在,所以输出false,&&是并且的意思,||表示前面一个执行失败才会执行后面
#例二:使用-z选项(如果测试字符串的长度为0,则表达式成立)
[root@shell ~]# test -z 'guoke' && echo 1 || echo 00 #因为测试的字符串为guoke,不为空值,所以为假输出0
[root@shell ~]# char='guoke'
[root@shell ~]# test -z '$char' && echo 1 || echo 0
0 #因为guoke赋值给了char,所以也不是空值,输出0
[root@shell ~]# char=''
[root@shell ~]# test -z '$char' && echo 1 || echo 0
1 #char为空值,所以长度为0,表达式成立输出1
#1.2.[]中括号条件测试语法和使用
#语法格式:[ <测试表达式> ]
#注意点:中括号内部的两端都要有空格,[]和test用法一样,test的判断选项也可以在[]中用
#输入两端都有空格的技巧:先输入一对中括号,然后退一个格,输入两个空格,再退一个格
#例子:利用[]加-f选项(如果文件存在且为普通文件则表达式就成立)
[root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1 || echo 00 #文件不存在所以输出0
[root@shell ~]# touch /tmp/guoke.txt
[root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1 || echo 0
1 #文件存在且为一个普通文件,则输出1
[root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1
1
#1.3.[[]] 双中括号条件测试语法及使用
#语法格式:[[ <测试表达式> ]]
#注意点:双中括号的两端需要有空格
#例子:判断文件存在且为一个普通文件
[root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1 || echo 00 #文件不存在所以条件不成立,输出0
[root@shell ~]# touch /tmp/test.txt
[root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1 || echo 0
1 #文件存在且为普通文件,条件成立,输出1
[root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1
1
#1.4.特殊条件测试表达式例子
#判断条件测试表达式的条件成立或不成立后,还需要执行多条命令语句的语法,不用if测试表达式的格式
#当条件1成立时,同时执行多条命令
test 条件1 && {}[ 条件1 ] && { 命令1 命令2}[[ 条件1 ]] && {}
#例子:当条件成立的时候就执行后面的命令
[root@shell ~]# cat test.sh#!/bin/bash[ $1 -eq 3 ] && {echo 1echo 2echo 3}[root@shell ~]# sh test.sh 3 #传参123
#上面的判断相当于下面if语句的效果
if [ 条件1 ];then 命令1 命令2fi
#关于条件测试表达式的总结
#1.test和[]、[[]]的功能有所重合,因此在工作中选择一种适合自己的一种用,其他的可以看懂别人的写的脚本就好了,可以同man test查看更多参数用法
#2.测试表达式test、[]、[[]]、(())区别总结
测试表达式符号 test [] [[]] (())边界是否需要空格 需要 需要 需要 不需要逻辑操作符 !、-a、-o !、-a、-o !、&&、|| !、&&、||整数比较操作符 -eq -gt -lt -ge -le(test,[],[[]]) = < > >= <=字符串比较操作符 =、==、!= (全部支持)是否支持通配符匹配 不支持 不支持 支持 不支持
2.文件表达式
#常用的文件测试操作符
#常用操作符 #说明-f 文件,全称file #文件存在且为普通文件则为真,表达式成立-d 文件,全称directory #文件存在且为目录则为真,表达式成立-s 文件,全称size #文件存在且大小不为0为真-e 文件,全称exist #文件存在则为真-r 文件,全称read #文件存在且为可读则为真,表达式成立-w 文件,全称write #文件存在且可写为真,表达式成立-x 文件,全称executable #文件存在且可执行为真-L 文件,全称link #文件存在且为链接文件为真f1 -nt f2,英文newer than #文件f1比文件f2新则为真,根据文件修改时间计算f1 -ot f2,英文older than #文件f1比文件f2旧为真,根据修改时间计算
#例子:#1.-f,判断文件是否存在且为普通文件
[root@shell ~]# touch test
[root@shell ~]# ls -l test
-rw-r--r-- 1 root root 0 Mar 18 16:02 test
[root@shell ~]# [ -f test ] && echo 1 || echo 0
1 #解析:因为文件存在且为普通文件,所以为真输出1
#2.-d,判断文件是否存在且为目录
[root@shell ~]# mkdir test1
[root@shell ~]# [ -d test1 ] && echo 1 || echo 0
1 #因为文件存在且为目录,所以为真输出1,如果不存在就输出0
#3.测试文件属性:r,w,x
[root@shell ~]# ls -ld test
-rw-r--r-- 1 root root 0 Mar 18 16:02 test
[root@shell ~]# [ -r test ] && echo 1 || echo 0
1 #文件存在且可读,为真,输出1
[root@shell ~]# [ -w test ] && echo 1 || echo 0
1 #文件存在且可写,为真,输出1
[root@shell ~]# [ -x test ] && echo 1 || echo 0
0 #文件不可执行,不为真,所以输出0
[root@shell ~]# chmod +x test
[root@shell ~]# [ -x test ] && echo 1 || echo 0
1 #加了可执行权限就为真成立了
#提示:测试文件的读、写、执行等属性,不光是根据文件属性rwx的标识来判断,还要看当前执行测试的用户是否真的可以按照对应的权限操作该文件
#测试时变量的特殊写法及问题
#用[]测试变量时,如果被测试的变量不加双引号,那么测试结果可能会是不正确的
#例子
[root@shell ~]# echo $test #不存在的变量[root@shell ~]# [ -f $test ] && echo 1 || echo 0 #不加引号返回的结果时错误的1[root@shell ~]# [ -f '$test' ] && echo 1 || echo 0 #添加以后返回的结果是正确的0
#注意点:做测试判断时,不一定非要按照前面的如果成立了输出什么,不成立输出什么,可以直接做部分判断
[root@shell ~]# [ -x test ] && echo 1 #如果test文件可执行,就输出1,否则不做任何输出[root@shell ~]# [ -f /etc ] || echo 0 #如果前面执行失败就输出0,否则不做任何输出0
3.字符串表达式
#字符串表达式作用:比较两个字符串是否相同、测试字符串的长度是否为0、字符串是否为null等
#常用的字符串测试操作符
#常用字符串操作符 #说明-z '字符串' 如果字符串长度为0则为真,-n '字符串' 如果字符串长度不为0则为真,'字符串1' = '字符串2' 如果字符串1等于字符串2则为真,可以使用==代替='字符串1' != '字符串2' 如果字符串1不等于字符串2则为真,不能使用!==代替!=
#提示:
#1.上面的字符串测试操作符必须要有''引起来
#2.比较符号两端要有空格
#3.-n 比较字符串长度是否不为0,如果不为0则为真,用法 [ -n '$my' ]
#4.-z 比较字符串长度是否为0,如果为0则为真,用法 [ -z '$my' ]
#例1:-n,-z参数应用
[root@shell ~]# [ -n 'abc' ] && echo 1 || echo 01 #-n是不为空则为真,字符串长度为abc,所以长度不是为0,为真输出1
[root@shell ~]# test -n 'aa' && echo 1 || echo 01 [root@shell ~]# test -n '' && echo 1 || echo 00 #字符串为空,不为真,数以输出0
[root@shell ~]# var='test'[root@shell ~]# [ -n '$var' ] && echo 1|| echo 01[root@shell ~]# [ -z '$var' ] && echo 1|| echo 00 #-z是为空值为真,不为空值为假,所以输出0
[root@shell ~]# [ 'aa' = 'aa' ] && echo 1 || echo 01 #字符串相等,所以长度为0,为
#例二:进行字符串比较时,如果等号两端没有空格带来的问题
[root@shell ~]# [ 'abc'='1' ]&& echo 1 || echo 0 1 #等号两边没有空格,明显是不成立的也输出了1
[root@shell ~]# [ 'abc' = '1' ]&& echo 1 || echo 0 0 #正常现象
#总结:字符串比较时若等号两端没有空格,则会导致判断出现逻辑错误,即使语句没有问题,但是结果依然可能不对
#例三:字符串不加引号可能带来的问题
[root@shell ~]# var='' #将变量内容设置为空[root@shell ~]# [ -n '$var' ] && echo 1 || echo 00 #-n是值不为空则为真,因为变量内容为0,为空值,所以不为真,输出0
[root@shell ~]# [ -n $var ] && echo 1 || echo 01 #不加双引号导致返回结果错误[root@shell ~]# [ -z '$var' ]&& echo 1 || echo 01 #-z是字符串长度为0,则为真
#查看有关双引号和等号两端空格的生产系统标准
[root@shell ~]# sed -n '30,31p' /etc/init.d/network# Check that networking is up.[ '${NETWORKING}' = 'no' ] && exit 6
4.整数表达式
#整数二元比较操作符
在test及[]中使用的比较符号 在[[]]和(())中使用的比较符号 说明-eq == 或 = 相等,全称equal-ne != 不相等,全称not qeual-gt > 大于,全称greater than-ge >= 大于等于,全称为greater equal-lt < 小于,全称less than-le <= 小于等于,全称less equal
#注意:'<'和'>'在[]中括号里面需要转义,对于数字不转义的结果可能不会报错,但是结果可能不对,=和!=在[]不用转义
#例子
[root@shell ~]# [ 2 > 3 ] && echo 1 || echo 01 #结果应该返回0,但是不转义返回了1是错误的[root@shell ~]# [ 2 \> 3 ] && echo 1 || echo 00 #进行转义之后输出正确[root@shell ~]# [ 2 < 1 ] && echo 1 || echo 01[root@shell ~]# [ 2 \< 1 ] && echo 1 || echo 00
#整数比较的推荐用法,使用-eq,-lt,-gt
#例子
[root@shell ~]# [ 13 -lt 24 ] && echo 1
1 #13小于24结果为真就输出1
5.逻辑操作符
#常用的逻辑操作符
在test及[]中使用的比较符号 在[[]]和(())中使用的比较符号 说明 -a && and,且,两端都为真,则结果为真 -o || or,或,两端有一个为真,则结果为真 ! ! not,非,两端相反,则结果为真
#提示
1、逻辑操作符前后的表达式是否成立,一般用真假来表示2、“!”的中文意思是反,即与一个逻辑值相反的逻辑值3、-a的中文意思是“与”(and或&&),前后两个逻辑值都为“真”,综合返回值才为真,否则为假4、-o的中文意思是“或”(or或||),前后两个逻辑值只要有一个为真,返回值就为真5、连接两行[]、test或[[]]的表达式可用&&或||
#提示:中括号里面不能使用&&字符串,否则报错,在[[]]和(())里面就可以用,可参考上面列出的
[root@shell ~]# [ -f '$f1' && -f '$f2' ] && echo 1 || echo 0-bash: [: missing `]'0
#例一:
[root@shell ~]# f1=/etc/rc.local[root@shell ~]# f2=/etc/services[root@shell ~]# [ -f '$f1' -a -f '$f2' ] && echo 1 || echo 01 #判断如果f1和f2变量的文件存在且为文件的话,就为真,输出1,如果一个不为真,那么久不为真,就输出0
[root@shell ~]# [[ -f '$f1' && -f '$f2' ]] && echo 1 || echo 0
1 #在[[]]双中括号中就可以使用&&
[root@shell ~]# [ -f '$f1' ]&&[ -f '$f2' ] && echo 1 || echo 0
1 #或者在两个[]之间使用&&也可以
#例二:
[root@shell ~]# a=1[root@shell ~]# b=2[root@shell ~]# [ '$a' -eq 2 -a '$b' -eq 2 ] && echo 1 || echo 00 #如果变量a等于2且变量b也等于2,则为真,否则为假,输出0
[root@shell ~]# [ '$a' -eq 1 -a '$b' -eq 2 ] && echo 1 || echo 01[root@shell ~]# [ '$a' -eq 1 -o '$b' -eq 2 ] && echo 1 || echo 01 #如果变量a等于或变量b等于2,则为真,输出1,-o是或,有一个条件成立则为真
[root@shell ~]# [ '$a' -eq 2 -o '$b' -eq 3 ] && echo 1 || echo 00