本文档主要讲解Shell变量的数值计算与实践shell
基本大纲:express
1.Shell脚本的条件测试编程
2.文件测试表达式bash
3.字符串测试表达式less
4.整数二元比较操做符ide
5.逻辑操做符测试
6.测试表达式test、[]、[[]]、(())的区别总结spa
一:shell脚本的条件测试token
1)条件测试方法综述 ip
一般,在bash的各类条件结构和流程控制结构中都要进行各类测试,而后根据测试结构执行不一样的操做,有时也会与if等条件语句相结合,来完成测试判断,以减小程序运行的错误。
执行条件测试表达式后一般会返回"真"或"假",就像执行命令后返回的值为0表示真,非0表示假同样。
Bash编程中条件测试经常使用的语法:
条件测试语法 |
说明 |
语法一:test<测试表达式> |
这是利用test命令进行测试表达式的方法。test命令和"<测试表达式>"之间至少有一个空格; |
语法二:[<测试表达式>] |
这是经过[](单中括号)进行条件测试表达式的方法,和test命令的用法相同。[]的边界和内容之间至少有一个空格; |
语法三:[[<测试表达式>]] |
这是经过[[]](双中括号)进行条件测试表达式的方法。是比test和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格; |
语法四:((<测试表达式>)) |
这是经过(())(双小括号)进行条件测试表达式的方法,通常用于if语句里。(())(双小括号)两端不须要有空格;通常都少用到 |
针对上表格有几个注意事项须要说明下:
语法一中的test命令和语法二中的[]是等价的。语法三种的[[]]为扩展的test命令,语法四中的(())经常使用语计算,建议使用相对友好的语法二,即中括号[]的语法格式。
在[[]]中可使用通配符等进行模式匹配,这是区别于其余几种语法格式的地方。
&&、||、>、<\等操做符能够应用于[[]]中,但不能应用于[]中,在[]中通常用-a、-o、-gt(用于整数)、-lt(用于整数)代替上述操做符。
对于整数的关系运算,也可使用shell的算数运算符(())。
2)语法一:test条件测试的语法及示例
test <测试表达式> test -f file && echo true || echo false #该语句表示若是file存在,则输出true,不然(||)输出false。这里的&&是而且的意思。test的-f参数用于测试文件是否为普通文件,test命令若执行成功(为真),则执行&&后面的命令, 若是执行失败,则执行||后面的命令 范例1:在test命令中使用-f选项测试文件是否存在 [root@aliyun tj]# test -f file && echo true || echo false false [root@aliyun tj]# touch file [root@aliyun tj]# test -f file && echo true || echo false true 范例2:在test命令中使用-z选项测试字符串长度,为0则表达式成立 [root@aliyun tj]# test -z "ywxi" && echo 1 || echo 0 #字符串长度不为0,因此表达式为假,返回结果为0 0 [root@aliyun tj]# char="ywxi" [root@aliyun tj]# test -z "$char" && echo 1 || echo 0 0 [root@aliyun tj]# char="" [root@aliyun tj]# test -z "$char" && echo 1 || echo 0 1
3)语法二:中括号[]条件测试语法及示例
[]条件测试的语法格式为[<测试表达式>] [ -f file ] && echo true || echo false #注意:中括号内部的两端要有空格,[]和test等价,即test的全部判断选项均可以直接[]里使用。 范例1:利用[]加-f选项(文件存在且为普通文件则表达式成立)测试文件。 [root@aliyun tj]# [ -f /tmp/file.txt ] && echo true || echo false #文件不存在,因此输出false false [root@aliyun tj]# touch /tmp/file.txt [root@aliyun tj]# [ -f /tmp/file.txt ] && echo true || echo false #文件存在,全部输出true true [root@aliyun tj]# [ -f /tmp/file.txt ] && echo true true [root@aliyun tj]# [ -f /tmp/file.txt ] || echo false [root@aliyun tj]# [ -f /tmp/file ] || echo false #文件不存在,因此不成立,因此执行||后面的输出 false
4)语法三:[[]]条件测试语法及示例
[[]]条件测试的语法格式为:[[<测试表达式>]] #注意:双中括号里的两端也要有空格。 #[[]]和[]与test的主要区别在于,在[[]]中可使用通配符等进行模式匹配;而且&&、||、>、<等操做符能够应用在[[]]中,但不能应用在[]中,在[]中通常使用-a、-o、-gt等来代替 范例1: [root@aliyun tj]# [[ -f /tmp/file.txt ]] && echo true || echo false true [root@aliyun tj]# [[ -f /tmp/test.txt ]] && echo true || echo false false [root@aliyun tj]# touch /tmp/test.txt [root@aliyun tj]# [[ -f /tmp/test.txt ]] && echo true || echo false true [root@aliyun tj]# rm -rf /tmp/test.txt [root@aliyun tj]# [[ -f /tmp/test.txt ]] && echo true || echo false false
二:文件测试表达式
1)文件测试表达式的用法以下表;
经常使用文件测试操做符 |
说明 |
-d文件,d的全拼为directory |
文件存在且为目录则为真,即测试表达式成立; |
-f文件,f的全拼为file |
文件存在且为普通文件则为真,即测试表达式成立; |
-e文件,e的全拼为exist |
文件存在则为真,即测试表达式成立。区别于"-f","-e"不能辨别是目录仍是文件; |
-r文件,r的全拼为read |
文件存在且可读测试为真,即测试表达式成立; |
-s文件,s的全拼为size |
文件存在且文件大小不为0则为真,即测试表达式成立; |
-w文件,w的全拼为write |
文件存在则可写为真,即测试表达式成立; |
-x文件,x的全拼为executable |
文件存在且可执行为真,即测试表达式成立; |
-L文件,L的全拼为link |
文件存在且连接文件则为真,即测试表达式成立; |
f1 -nt f2,nt的全拼为newer than |
文件f1比文件f2新则为真,即测试表达式成立。根据文件的修改时间来计算; |
f1 -ot f2,nt的全拼为older than |
文件f1比文件f2旧则为真,即测试表达式成立。根据文件的修改时间来计算; |
2)普通文件和目录测试表达式示例:
[root@aliyun tj]# touch ywxi.txt [root@aliyun tj]# ls -l ywxi.txt -rw-r--r-- 1 root root 0 May 31 13:59 ywxi.txt [root@aliyun tj]# [ -f ywxi.txt ] && echo 1 || echo 0 #文件存在,表达式成立,输出为1 1 [root@aliyun tj]# mkdir ywxi [root@aliyun tj]# ls -ld ywxi drwxr-xr-x 2 root root 4096 May 31 14:02 ywxi [root@aliyun tj]# [ -f ywxi ] && echo 1 || echo 0 #-f判断文件,ywxi是目录名,全部表达式不成立,则输出为0 0 [root@aliyun tj]# [ -d ywxi ] && echo 1 || echo 0 1 [root@aliyun tj]# [ -d ywxi.txt ] && echo 1 || echo 0 0 [root@aliyun tj]# [ -e ywxi ] && echo 1 || echo 0 #不区别目录和文件,存在即为表达式成立,输出为1 1 [root@aliyun tj]# [ -e ywxi.txt ] && echo 1 || echo 0 1
3)文件属性测试示例:
[root@aliyun tj]# ls -l ywxi.txt -rw-r--r-- 1 root root 0 May 31 13:59 ywxi.txt [root@aliyun tj]# [ -r ywxi.txt ] && echo 1 || echo 0 1 [root@aliyun tj]# [ -w ywxi.txt ] && echo 1 || echo 0 1 [root@aliyun tj]# [ -x ywxi.txt ] && echo 1 || echo 0 0 [root@aliyun tj]# chmod 001 ywxi.txt [root@aliyun tj]# ls -l ywxi.txt ---------x 1 root root 0 May 31 13:59 ywxi.txt [root@aliyun tj]# [ -w ywxi.txt ] && echo 1 || echo 0 #用户权限位没w,输出1是由于root用户确实能够写。这是root用户特殊的地方 1 [root@aliyun tj]# echo 'echo test' >ywxi.txt [root@aliyun tj]# [ -r ywxi.txt ] && echo 1 || echo 0 #用户权限位没r,输出1是由于root用户确实能够读 。这是root用户特殊的地方 1 [root@aliyun tj]# cat ywxi.txt test [root@aliyun tj]# [ -x ywxi.txt ] && echo 1 || echo 0 1 [root@aliyun tj]# ./ywxi.txt test 注意:测试文件的读、写、执行等属性,不光是根据文件属性rwx的标识来判断,还要看当前执行测试的用户是否真的能够按照对应的权限操做该文件。
4)测试Shell变量示例
[root@aliyun tj]# ls -la drwxr-xr-x 2 root root 4096 May 31 14:02 ywxi #目录 ---------x 1 root root 10 May 31 16:41 ywxi.txt #文件 [root@aliyun tj]# file1=/scripts/practice/tj/ywxi ; file2=/scripts/practice/tj/ywxi.txt [root@aliyun tj]# echo $file1 $file2 /scripts/practice/tj/ywxi /scripts/practice/tj/ywxi.txt #对目录测试 [root@aliyun tj]# [ -f "$file1" ] && echo 1 || echo 0 #不是文件,因此为假 0 [root@aliyun tj]# [ -d "$file1" ] && echo 1 || echo 0 #是目录,因此为真 1 [root@aliyun tj]# [ -s "$file1" ] && echo 1 || echo 0 #目录存在且大小不为0,因此为真 1 [root@aliyun tj]# [ -e "$file1" ] && echo 1 || echo 0 #目录存在即为真 1 #对文件测试 [root@aliyun tj]# [ -f "$file2" ] && echo 1 || echo 0 #是文件,因此为真 1 [root@aliyun tj]# [ -d "$file2" ] && echo 1 || echo 0 #不是目录,因此为假 0 [root@aliyun tj]# [ -e "$file2" ] && echo 1 || echo 0 #文件存在,因此为真 1 [root@aliyun tj]# [ -s "$file2" ] && echo 1 || echo 0 #文件存在且大小不为0,因此为真 1 #测试变量的特殊写法及问题 [root@aliyun tj]# echo $ywxi #变量为空 [root@aliyun tj]# [ -f $ywxi ] && echo 1 || echo 0 #变量不存在,但还返回1,逻辑就不对了 1 [root@aliyun tj]# [ -f "$ywxi" ] && echo 1 || echo 0 #变量加上双引号,逻辑就对了 0 #对于文件实在路径,双引号加与不加就没区别了 [root@aliyun tj]# [ -f /etc/services ] && echo 1 || echo 0 1 [root@aliyun tj]# [ -f "/etc/services" ] && echo 1 || echo 0 1 #在生产环境中,系统NFS启动脚本的条件测试 [root@localhost practice]# grep '&&' /etc/init.d/nfs|head -2 [ -f /etc/sysconfig/network ] && . /etc/sysconfig/network #若是/etc/sysconfig/network文件存在,则加载文件,不用加双引 [ -f /etc/sysconfig/nfs ] && . /etc/sysconfig/nfs #若是/etc/sysconfig/nfs文件存在,则加载文件,不用加双引
三:字符串测试表达式
1)字符测试表达式
字符串测试操做符的做用包括;比较两个字符串是否相同、测试字符串的长度是否为零,字符串是否为NULL等;
经常使用字符串测试操做符 |
说明 |
-n"字符串" |
若字符串的长度不为0,则为真,即测试表达式成立,n能够理解为no zero; |
-z"字符串" |
若字符串的长度为0,则为真,即测试表达式成立,z能够理解为zero的缩写; |
"串1"= "串2" |
若字符串1等于字符串2,则为真,即测试表达式成立,能够用"=="代替"="; |
"串1"!="串2" |
若字符串1不等于字符串2,则为真,即测试表达式成立,但不能用"!=="代替"!="; |
如下是针对字符串测试操做符的提示:
对于字符串的测试,必定要将字符串加双引号以后在进行比较。如[-n $myvar],特别是使用[]的场景;
比较符号(例如=和!=)的两端必定要有空格;
"!="和"="可用于比较两个字符串是否相同;
2)字符串条件表达式测试实践:
[root@localhost practice]# [ -n "a" ] && echo 1 || echo 0 #长度不为0,因此为真 1 [root@localhost practice]# test -n "a" && echo 1 || echo 0 1 [root@localhost practice]# test -n "" && echo 1 || echo 0 #长度为0,因此为假 0 [root@localhost practice]# [ -n "" ] && echo 1 || echo 0 0 [root@localhost practice]# a=ywxi [root@localhost practice]# echo $a ywxi [root@localhost practice]# [ -n "$a" ] && echo 1 || echo 0 #长度不为0,因此为真 1 [root@localhost practice]# [ -n $a ] && echo 1 || echo 0 1 [root@localhost practice]# [ -z $a ] && echo 1 || echo 0 0 [root@localhost practice]# [ -z "$a" ] && echo 1 || echo 0 0 [root@localhost practice]# [ "abc" = "abd" ] && echo 1 || echo 0 #字符串不一致,因此为假 0 [root@localhost practice]# [ "abc" = "abc" ] && echo 1 || echo 0 1 [root@localhost practice]# [ "$a" = "ywxi" ] && echo 1 || echo 0 #解析了变量的值与ywxi一致 1 [root@localhost practice]# [ $a = "ywxi" ] && echo 1 || echo 0 #解析了变量的值与ywxi一致 1 [root@localhost practice]# [ '$a' = "ywxi" ] && echo 1 || echo 0 #原样输出,没解析了变量的值,不与ywxi一致,因此为假 0 [root@localhost practice]# [ "$a" != "ywxi" ] && echo 1 || echo 0 #解析了$a的值与ywxi一致,是相等的。不等于不成立,因此为假 0
3)字符串测试生产案例:
[root@aliyun tj]# sed -n '30,31p' /etc/init.d/network #这是系统网卡启动脚本 # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 #字符串变量和字符串都加了双引号,比较符号"="两端也都有空格
四:整数二元比较操做符
1)整数二元比较操做符介绍
在[]以及test中使用的比较符号 |
在(())和[[]]中使用的比较符号 |
说明 |
-eq |
==或= |
相等,全拼为equal |
-ne |
!= |
不相等,全拼为not equal |
-gt |
> |
大于,全拼为gerater than |
-ge |
>= |
大于等于,全拼为gerater equal |
-lt |
< |
小于,全拼为less than |
-le |
<= |
小于等于,全拼为less equal |
如下是针对上述符号的特别说明:
"="和"!="也能够在[]中做比较使用,但在[]中使用包含">"和"<"的符号时,须要用反斜线转义,有时不转义虽然语法不会报错,可是结果可能会不对;
也能够在[[]]中使用包含"-gt"和"-lt"的符号,可是不建议这样使用;
比较符号两端也要有空格;
2)二元数字在[]中使用"<"和">"非标准符号的比较
[root@aliyun tj]# [ 2 > 1 ] && echo 1 || echo 0 1 [root@aliyun tj]# [ 2 < 1 ] && echo 1 || echo 0 #2<1的结果1逻辑是不对的,应该返回0才是正常的 1 [root@aliyun tj]# [ 2 \< 1 ] && echo 1 || echo 0 #用\转义后结果逻辑就正常了 0 [root@aliyun tj]# [ 2 = 1 ] && echo 1 || echo 0 0 [root@aliyun tj]# [ 2 = 2 ] && echo 1 || echo 0 1 [root@aliyun tj]# [ 2 != 2 ] && echo 1 || echo 0 0
3)二元数字在[]中使用-gt、-le类符号的比较
[root@aliyun tj]# [ 2 -gt 1 ] && echo 1 || echo 0 1 [root@aliyun tj]# [ 2 -ge 1 ] && echo 1 || echo 0 1 [root@aliyun tj]# [ 2 -le 1 ] && echo 1 || echo 0 0 [root@aliyun tj]# [ 2 -lt 1 ] && echo 1 || echo 0 0
4)二元数字配合不一样种类的操做符在[[]]中的比较
[root@aliyun tj]# [[ 1 > 2 ]] && echo 1 || echo 0 0 [root@aliyun tj]# [[ 1 < 2 ]] && echo 1 || echo 0 1 [root@aliyun tj]# [[ 1 = 2 ]] && echo 1 || echo 0 0 [root@aliyun tj]# [[ 1 != 2 ]] && echo 1 || echo 0 1 [root@aliyun tj]# [[ 1 -gt 2 ]] && echo 1 || echo 0 0 [root@aliyun tj]# [[ 1 -lt 2 ]] && echo 1 || echo 0 1 [root@aliyun tj]# [[ 1 -ne 2 ]] && echo 1 || echo 0 1 [root@aliyun tj]# [[ 1 -eq 2 ]] && echo 1 || echo 0 0
5)二元数字在(( ))中的比较
[root@aliyun tj]# ((2>1)) && echo 1 || echo 0 1 [root@aliyun tj]# ((2<1)) && echo 1 || echo 0 0 [root@aliyun tj]# ((2==1)) && echo 1 || echo 0 0 [root@aliyun tj]# ((2!==1)) && echo 1 || echo 0 -bash: ((: 2!==1: syntax error: operand expected (error token is "=1") #"!=="符号不可用,语法错误 0 [root@aliyun tj]# ((2!=1)) && echo 1 || echo 0 1
有关[]、[[]]、(())用法的小结:
证书加双引号的比较是对的
[[]]中用相似-eq等的写法是对的,[[]]中用相似>、<的写法也可能不对,有可能会只比较第一位,逻辑结果不对
[]中用相似>、<的写法在语法上虽然可能没错,但逻辑结果不对,可使用=、!=正确比较
(())中不能用相似-eq等的写法,可使用相似>、<的写法
五:逻辑操做符
1)逻辑操做符介绍
在[]和test中使用的操做符 |
在[[]]和(())中使用的操做符 |
说明 |
-a |
&& |
and,与,两端都为真,则结果为真 |
-o |
|| |
or,或,两端有一个为真,则结果为真 |
! |
! |
Not,非,两端相反,则结果为真 |
对于上述操做符,有以下提示:
逻辑操做符先后的表达式是否成立,通常用真假来表示;
"!"的中文意思是反,即与一个逻辑值相反的逻辑值;
-a的中文意思是"与"(and或&&),先后两个逻辑值都为"真",综合返回值才为"真",反之为"假";
-o的中文意思是"或"(or或||),先后2个逻辑值只要有一个为"真",返回值就为"真";
链接两含[]、test或[[]]的表达式可用&&或||;
2)逻辑操做符实践示例:
1.[]里的逻辑操做符配合文件测试表达式使用的示例
[root@aliyun tj]# f1=/etc/rc.local ;f2=/etc/services [root@aliyun tj]# echo $f1 $f2 /etc/rc.local /etc/services [root@aliyun tj]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0 #测试f1和f2两个变量是否都为文件,成立则输出1 1 [root@aliyun tj]# [ -f "$f1" -o -f "$f2" ] && echo 1 || echo 0 #测试f1和f2两个变量有一个是否为文件,成立则输出1 1 [root@aliyun tj]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0 #&&这是错误语法的提示 -bash: [: missing `]' 0 [root@aliyun tj]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0 #正确运用写法 1
2.[[]]里的逻辑操做符配合字符串的条件表达式使用的示例
[root@aliyun tj]# a="abc";b="def" [root@aliyun tj]# echo -ne "$a $b\n" abc def [root@aliyun tj]# [[ ! -n "$a" && "$a" = "$b" ]] && echo 1 || echo 0 #$a长度不为0而且$a等于$b是否成立,必须两个表达式同时成立 0 [root@aliyun tj]# [[ -z "$a" -o "$a" != "$b" ]] && echo 1 || echo 0 #内部用-a或-o会报错 -bash: syntax error in conditional expression -bash: syntax error near `-o' [root@aliyun tj]# [[ -z "$a" || "$a" != "$b" ]] && echo 1 || echo 0 1
3.(())逻辑操做符配合整数的条件表达式测试示例
[root@aliyun tj]# m=20;n=30 [root@aliyun tj]# ((m>15&&n>25)) && echo 1 || echo 0 1 [root@aliyun tj]# ((m>15||n>25)) && echo 1 || echo 0 1 [root@aliyun tj]# ((m>25||n>25)) && echo 1 || echo 0 1 [root@aliyun tj]# ((m>25||n>35)) && echo 1 || echo 0 0 [root@aliyun tj]# ((m>25 -a n>35)) && echo 1 || echo 0 -bash: ((: m>25 -a n>35: syntax error in expression (error token is "n>35") 0
示例总结:
“-a”和“-o”逻辑操做符号须要用于[]中
“&&”和“||”逻辑操做符号可用于[[]]或(())中,也能够在外部链接多个[]
注意,在[]和[[]]的两端及比较符号的两端,必需要有空格,可是对于(())不须要
六:测试表达式test、[]、[[]]、(())的区别总结
以下表所示:
测试表达式操做符 |
[] |
test |
[[]] |
(()) |
边界是否须要空格 |
须要 |
须要 |
须要 |
不须要 |
逻辑操做符 |
!、-a、-o |
!、-a、-o |
!、&&、|| |
!、&&、|| |
整数比较操做符 |
-eq、-gt、-lt、-ge、-le |
-eq、-gt、-lt、-ge、-le |
-eq、-gt、-lt、-ge、-le或=、>、<、>=、<= |
=、>、<、>=、<= |
字符串比较操做符 |
=、==、!= |
=、==、!= |
=、==、!= |
=、==、!= |
是否支持通配匹配符 |
不支持 |
不支持 |
支持 |
不支持 |