Shell 脚本的条件测试与比较
Shell 巩固和复习系列笔记,立个 Flag,之后不定时更新相关工作上可能遇到的 Shell 应用场景。
文章目录
1. Shell脚本的条件测试
在 bash 各种条件结构和流程控制结构中都要进行各种测试,然后根据测试结果执行不同的操作,有时也会与if等条件语句相结合,来完成测试判断,以减少程序运行的错误。
执行条件测试表达后通常会返回“真”或“假”,就像执行命令后的返回值为 0 表示真,非 0 表示假一样。
条件测试常用语法
条件测试语法 | 说明 |
---|---|
语法1:test <测试表达式> | 利用 test 命令进行条件测试表达式的方法,test 与表达式至少隔一个空格 |
语法2:[ <测试表达式> ] | 通过[](单括号)进行条件测试表达式的方法,与 test 命令用法相同,边界与表达式至少隔一个空格 |
语法3:[[ <测试表达式> ]] | 通过[[]](双中括号)进行条件测试表达式的方法,边界与表达式至少隔一个空格 |
语法4:((<测试表达式>)) | 通过(())(双小括号)进行条件测试表达式的方法,一般用于if语句,(())与表达式不需要留空格 |
说明:
- 语法1中的 test 命令和语法 2 中的[]等价,[[]]为扩展的 test 命令,(()) 常用于算数运算
- [[]](双中括号)可以使用通配符进行模式匹配,区别于其他语法模式
&&
、||
、!
、>
、<
等操作符可以用于 [[]] 中,但不能应用于 [] 中,在 [] 中一般用-a
、-o
、-gt(整数)
、-lt(整数)
等命令行参数代替操作符- 整数的关系运算,也可以使用 Shell 的算数运算符 (())
1.1 test条件测试
test
等价于[]
,三个基本作用就是判断文件、字符串、整数。支持使用与或非
将表达式连接起来
test 中可用的比较运算符只有 ==
和 !=
,两者都用于字符串比较的,不可用于整数比较,整数比较只能使用-eq
、-gt
这种参数形式,如需要使用大于>
或小于<
进行字符串的比较,必须加上转义符号如[ ab \< bc ]
[root@aurora study]# test -f test.txt && echo true || echo false
true
如果 test.txt
文件存在,输出 true,否则输出 false,-f 判断是否为普通文件
test -z “tuzaza” && echo 1 || echo 0
如果测试字符串的长度为 0 则输出 1,否则输出 0,-z
判断字符串的长度是否为 0
Tips:关于 test 测试表达式的更多知识可以执行man test
查看帮助
1.2 [](中括号)条件测试
[ -f /home/study/test.txt ] && echo 1 || echo 0
如果 /home/study/test.txt
文件存在,则输出 1,否则输出 0
1.3 [[]](双中括号)条件测试
[[]]
支持字符串的模式匹配,使用=
、~
等操作符支持 Shell 的正则表达式,逻辑组合不可以使用 test 的 -o
和 -a
,而是使用 &&
和 ||
字符串比较时把右边当做一个模式(字符串不加双引号,加双引号的字符串被认为是一个文本字符串),如[[ hello==hell? ]]
为真
[[ -f /home/study/test.txt ]] && echo 1 || echo 0
如果/home/study/test.txt
文件存在,则输出1,否则输出0
1.4 (())(双小括号)条件测试
(())
等价于let
,都只能对整数进行赋值运算
(())
算数表达式的值在if和while判断时不用在前面加$
,在echo输出值需要加$
,如echo $(( c = a+b+1 ))
使用 let 或 (()) 赋值的时候,也可以使用expr+
反引号替代
let a = $b + $c 等价于 a = `expr $b + $c`
a=1; let “a<0”; echo $?
a=1; ((a<0)); echo $?
if((a>0));then
echo x greater
else;
echo x not greater
fi
2.文件测试表达式
常用的文件测试操作符
常用文件测试操作符 | 说明 |
---|---|
-b文件,b 全拼为 block | 文件存在且为一个块(设备)文件为真 |
-c文件,c 全拼为 char | 文件存在且为一个字符(设备)文件为真 |
-d 文件,d 全拼为 directory | 文件存在且为目录文件为真 |
-f 文件,f 全拼为 file | 文件存在且为普通文件为真 |
-e 文件,e 全拼为 exist | 文件存在为真 |
-r 文件,r 全拼为 read | 文件存在且可读为真 |
-s文件,s 全拼为 size | 文件存在且其长度大于0为真 |
-S,文件,S 全拼为 Socket | 文件存在且是一个网络socket为真 |
-s 文件,s 全拼为 size | 文件存在且大小不为0为真 |
-w 文件,w 全拼为 write | 文件存在且可写为真 |
-x 文件,x 全拼为 executable | 文件存在且可执行为真 |
-p 文件,p 全拼为 pipe | 文件存在且为一个命令管道为真 |
-L 文件,L 全拼为 link | 文件存在且为链接文件为真 |
f1 -ef f2,ef 全拼为 equal file | 文件 f1 和 f2 拥有相同的索引号(可判断是否同一文件,硬链接) |
f1 –nt f2,nt 全拼为 newer than | 文件 f1 比文件 f2 新则为真,根据文件的修改时间计算 |
f1 –ot f2,ot 全拼为 older than | 文件 f1 比文件 f2 旧则为真,根据文件的修改时间计算 |
更多关于文件测试操作符可以man test
查看
2.1 特殊条件测试表达式案例
例子1.不用 if 测试表达式格式
当条件1成立时,同时执行命令1、命令2、命令3。不用 if 测试表达式格式如下:
[ 条件1 ] && {
命令1
命令2
命令3
}
[[ 条件1 ]] && {
命令1
命令2
命令3
}
上面的判断语句等价于下面if语句的效果。
if [ 条件 ]
then
命令1
命令2
命令3
fi
例子2.使用逻辑运算符||
当条件不成立时,执行大括号内的多条命令,使用逻辑运算符 ||
[ -f /etc ] || {
echo 1
echo 2
echo3
}
Tips: 如果把上述脚本写在一行内,大括号内的每个命令都需要用分号结尾。如[ -f /etc/services ] && { echo 1; echo 2; echo3; }
。虽然案例中的两种方式很简洁,却不如 if 条件语句容易理解。
3.字符串测试表达式
字符串测试操作符的作用包括:比较两个字符串是否相同、测试字符串的长度是否为 0、字符串是否为NULL等。
注: NULL,是通过 bash 区分零长度字符串和空字符串
字符串测试操作符
常用字符串测试操作符 | 说明 |
---|---|
-n 字符串 |
若字符串的长度不为0,则为真 |
-z 字符串 |
若字符串的长度为0,则为真 |
“串1” = “串2” | 若字符串1等于字符串2,则为真 |
“串1” != “串2” | 若字符串1不等于字符串2,则为真 |
说明:
- 对于字符串的测试,一定要将字符串加双引号之后再进行比较。如
[ -n “$myvar” ]
- 比较符号(例如
=
和!=
)的两端一定要有空格,否则即使不报错,结果也会出错 !=
和=
可用于两个字符串是否相同
例子—字符串测试操作符
[ -n “abc” ] && echo 1 || echo 0
test -n “abc” && echo 1 || echo 0
4. 整数二元比较操作符
整数二元比较操作符
在[]以及test中使用比较符号 | 在(())和[[]]中使用的比较符号 | 说明 |
---|---|---|
-eq | == 或 = | 相等(equal) |
-ne | != | 不相等(not equal) |
-gt | > | 大于(greater than) |
-ge | >= | 大于等于(greater equal) |
-lt | < | 小于(less than) |
-le | <= | 小于等于(less equal) |
说明:
=
和!=
也可以在[]中做比较,但在[]中使用包含>
和<
的符号时,需要用反斜线协议/
- 也可以在 [[]] 中使用包含
-gt
和-lt
的符号 - 比较符号两端也要有空格
例子1.二元数字在 [] 中使用 -gt、-le 类符号的比较
[ 2 -gt 1 ] && echo 1 || echo 0
[ 2 -ge 1 ] && echo 1 || echo 0
例子2.二次元数字配合不同类型发操作符在[[]]中的比较
[[ 65 < 66 ]] && echo 1 || echo 0
例子3.二元数字在 (()) 中的比较
(( 3 > 2 )) && echo 1 || echo 0
5. 逻辑操作符
逻辑操作符
在[]和test中使用的操作符 | 在[[]]和(()中使用的操作符 | 说明 |
---|---|---|
-a | && | And,与,两端为真结果为真 |
-o | || | Or,或,两端其一为真,结果为真 |
! | ! | Not,非,两端相反,结果为真 |
例子1.()(单中括号)文件测试
[ -f /etc/host -a -f /etc/services ] && echo 1 || echo 0
例子2.数值比较
[ 5 -eq 6 -o 5 -gt 3 ] && echo 1 || echo 0
((5==6||5>3)) && echo 1 || echo 0
6. 测试表达式test、[]、[[]]、(())的区别
不同符号测试表达式test、 []、[[]]、(())的区别
测试表达式符号 | []等价于test | [[]] | (())等价于let |
---|---|---|---|
边界是否需要空格 | 需要 | 需要 | 不需要 |
逻辑操作符 | !、-a、-o | !、&&、|| | !、&&、|| |
整数二元比较操作符(关系比较操作符) | -eq、-gt、lt、-ge、-le 或 >、< | -eq、-gt、lt、-ge、-le或=、>、<,不可以使用>=、<= | =、>、<、>=、<= |
字符串比较操作符 | =、==、!=、-n、-z,>、< 需要被转义 | =、==、!=、-n、-z,>、< 不需要被转义 | =、==、!= |
文件比较操作符 | -r、-l、-w、-x、-f、-d、-s、-nt、-ot | -r、-l、-w、-x、-f、-d、-s、-nt、-ot | 不支持 |
数学运算符 | +、-、*、/、% | 不支持 | +、-、*、/、% |
是否支持通配符匹配 | 不支持 | 支持 | 不支持 |
组合 | 用各自逻辑符号连接的数字(运算)测试、文 件测试、字符测试 |