1.测试内容 2.测试方法 3.命令执行 |
在shell脚本中应用条件测试时,关键是“测试表达式”。在条件语句中测试时首先分清楚测试什么类型的信息:数字、字符串、还是一个文件,要么就是一个逻辑关系。当遇到不同的测试类型时自然就有不同的“测试属性”,理解这个测试属性是必须的。不然就不知道从何处下手。
判断的返回值:真、假。
当判断的条件是一个命令时,始终认为是返回为真;缺省表达式,返回为假。
命令 | 用法 |
---|---|
test | test EXPRESSION |
[ | [ EXPRESSION ] |
例子:缺省表达式,默认为“假”
[view@payqa2 ~]$ [ ] && echo "true" [view@payqa2 ~]$ [ ! ] && echo "true" true
1.测试内容
表达式的“测试属性”分类
1.1.字符串测试
1.2.数字比较
1.3.文件测试
1.4.逻辑判断
1.1.字符串测试(判断字符串相等、为空、不为空)
使用时,与表达式左右要有一个空格分开。
表达式用法
test | [ | ||
---|---|---|---|
test $lastuser | [ $loguser ] ① |
为空 | |
test $lastuser == $loguser |
[ $loguser == "sunny" ] |
相等 | |
test -n lastuser | [ -n $lastuser ] ② | 非空 | |
test -z loguser | [ -z $loguser ] ③ | 为空 | |
比较时“==”两边保留空格,赋值时取消空格。 |
① 测试为空、不为空时,条件判断执行的语句
$ cat string_is_null.sh #!/bin/bash # if [ $1 ] then echo 'Execute then. true' else echo 'Execute else. false' fi
为空时,执行了else语句;不为空,执行了then语句。
$ ./string_is_null.sh Execute else. false $ ./string_is_null.sh hello Execute then. true
② “-n”如何影响if选择语句
$ cat string_n.sh #!/bin/bash # judge(){ if [ -n $1 ] then echo 'Execute then. true' else echo 'Execute else. false' fi } K="hello" S="" echo -ne 'K="hello",\t[ -n $K]\t' judge $K echo -ne 'S="",\t\t[ -n $S]\t' judge $S $ ./string_n.sh K="hello", [ -n $K] Execute then. true S="", [ -n $S] Execute then. true
测试结果,令人吃惊!
③ 把上边“-n”替换成“-z”
$ ./string_z.sh K="hello",[ -z $K] Execute else. false S="",[ -z $S] Execute then. true
为空时,执行了then语句;不为空,执行了else语句。
④ 测试位置变量的有无
存在位置变量的时候,不提示;不存在位置变量时,提示未知变量为空。
# cat test.sh #!/bin/bash # if [ -z $1 ];then echo '$1 is null.' fi # ./test.sh 7 # ./test.sh hello # ./test.sh $1 is null.
也可以通过这个小程序来测试脚本里使用了某个环境变量(ZCW_TS)是否存在。
⑤比较时竟然可以用“=”
阅读tomcat脚本时发现的(setclasspath.sh)
[root@iZm5e7mrdpxqswsmtrugo6Z tmp]# cat haha.sh #!/bin/bash if [ "x${hh}" = "x" ]; then echo "My god, = is ok." else echo "he he." fi [root@iZm5e7mrdpxqswsmtrugo6Z tmp]# ./haha.sh My god, = is ok.
1.2.数字比较(整数比较大小、等于)
表达式用法
expr | test | [ | 说明 |
---|---|---|---|
$age1 -eq $age2 $age1 -ne $age2 |
test $age1 -eq $age2 test $age1 -ne $age2 |
[ $age1 -eq $age2 ] [ $age1 -ne $age2 ] |
等于 不等于 |
$age1 -gt $age2 $age1 -lt $age2 |
test $age1 -gt $age1 test $age2 -lt $age2 |
[ $age1 -gt $age1 ] [ $age2 -lt $age2 ] |
大于 小于 |
$age1 -ge $age1 $age2 -le $age2 |
test $age1 -ge $age1 test $age2 -le $age2 |
[ $age1 -ge $age1 ] [ $age2 -le $age2 ] |
大等于 小等于 |
*举例说明
$int1 -eq $int2: # 数字相等 $int1 -ge $int2: # int1 ≥ int2 $int1 -gt $int2: # 〉 $int1 -le $int2: # ≤ $int1 -lt $int2: # 〈 $int1 -ne $int2: # ≠
例子:当k的值大于3时,循环结束。
#!/bin/bash declare -i k=0 while true; do if [ $k -gt 3 ]; then exit; else let k+=1 fi echo $k done
1.3.文件测试
表达式用法
test | [ | 说明 |
---|---|---|
-b /dev/cdrom | [ -b /dev/cdrom ] | 存在且为块文件 |
-c /etc/inittab |
[ -c /etc/fstab ] | 存在……字符文件 |
-d /data01 |
…… | ……且为目录文件 |
-e /~/.ssh/keys |
…… | ……存在 |
-s /~/.ssh/keys | …… | 是否非空 |
-f /etc/http/conf.d/ssl.cf |
…… | 存在且为常规文件 |
-w /data01/tmp/http.log |
…… | ……可写 |
-L /data01/tmp/http.log |
…… | ……符号链接 |
-u /data01/tmp/http.log |
…… | 设置suid位 |
-r /data01/tmp/http.log | …… | 存在且可读 |
-x /dinglicom/bin/httpd |
…… | ……可执行 |
*说明
file1 -nt file2:文件 file1 更新一些
file1 -ot file2:旧
-d file:file文件存在,并且是一个目录
-e file:文件存在
-h file:文件存在,并且是一个符号链接
-L file:“同上”
-r file:文件存在,并且被赋予了“读”权限
-w file:文件存在,并且被赋予了“写”权限
-x file:文件存在,并且被赋予了“执行”(“进入目录”)权限
-s file:文件存在,并且大小大于零
-S file:文件存在,并且是一个套接字文件
[web@h p]$ test -x dir_perm_test/ [web@h p]$ echo $? 1 [web@h p]$ ll dir_perm_test/ total 20 drw------- 2 web web 4096 Apr 8 01:44 dir_perm_test [web@h p]$ ll dir_perm_test/ ls: cannot access dir_perm_test/file1: Permission denied ls: cannot access dir_perm_test/file4: Permission denied ls: cannot access dir_perm_test/file2: Permission denied ls: cannot access dir_perm_test/file3: Permission denied total 0 -????????? ? ? ? ? ? file1 -????????? ? ? ? ? ? file2 -????????? ? ? ? ? ? file3 -????????? ? ? ? ? ? file4 [web@h p]$ cd dir_perm_test/ -bash: cd: dir_perm_test/: Permission denied [web@h p]$ chmod u+x dir_perm_test/;cd dir_perm_test/ [web@h p]$ touch file5 [web@h p]$ test -s file5 [web@h p]$ echo $? 1
1.4.逻辑判断组合
“逻辑判断组合”就像胶水一样把上边“3类”逻辑判断结合起来。
表达式用法
符号 |
含义 |
---|---|
! | 非 |
-a | 与 |
-o | 或 |
逻辑判断在脚本中的应用:
错误示范(组合字符串判断):
#!/bin/bash # clear # DISPLAY="Usage show.\n d/D show disks usages.\n m/M show memory usages.\n s/S show swap usages.\n By the way, if you want exit this script, input 'quit' or 'q'. " CHOICE="" # echo -e $DISPLAY read -p "Your choice: " CHOICE # #while [ $CHOICE != "quit" ] while [ $CHOICE != "quit" -o $CHOICE != "q" ] do # test #echo $CHOICE # while 1 case $CHOICE in d|D) echo "Disk info:" df -Ph ;; m|M) echo "Memory info:" free -m | grep -v "swap" ;; s|S) echo "Swap info:" free -m | grep -i "swap" ;; *) echo -e "\tUnkown optios." sleep 1 echo -e $DISPLAY esac # while 2 read -p "Once more. Your choice: " CHOICE # test #echo $CHOICE done
脚本执行后无法退出,错误就出在逻辑判断上。
正确示范:
while [ $CHOICE != "quit" -a $CHOICE != "q" ]
条件判断由于使用了逻辑组合“-o”、“-a”,分别需要对于前后两个逻辑判断计算结果。需要退出时,必须判断为假。当使用了组合时,会综合判断。
因为,“或”在满足后边逻辑判断为“假”需要退出时,前边判断为真,后边判断失效,整体结果为真,程序继续执行;反之,前边逻辑判断满足退出条件时,为假,会继续执行后边逻辑判断为“真”的条件测试(前边为假的“或”运算,后边判断不失效),整体结果依然为真;于是,循环体无法退出。
当选择“与”时,任意一个退出满足条件满足了即退出循环体。若前边判断为“假”,后边失效,整体结果为“假”,循环终止;当前边为“真”时,后边判断继续,进行为“假”的判断,整体结果为假
*说明
缺省表达式,返回为假。
[web@h p]$ test [web@h p]$ echo $? 1 [web@h p]$ test da [web@h p]$ echo $? 0
[ -d $LOCALDIRECTORY ] && $RM -fr $LOCALDIRECTORY [ ! -d $LOCALDIRECTORY ] && $MKDIR -pv $LOCALDIRECTORY
--------------------------
小括号($(cat /etc/inittab))用来运行命令,中括号([ i -eq j ])用来做条件判断,大括号(${user}1)用来界变量定字符串长度。两个小括号套用,在 for循环 里使用、或者 数字运算 。
--------------------------
2.测试方法
测试文件属性、测试字符串、数字比较。
用法 |
说明 |
---|---|
-a file |
文件存在为真 |
-b file |
是块文件为真 |
-c file |
是字符文件为真 |
-d file |
是目录为真 |
-e file |
文件存在为真 |
-f file |
是常规文件为真 |
-g file |
文件存在,且set-group-id为真 |
-h file |
文件为符号链接为真 |
-k file |
|
-p file |
|
-r file |
可读文件为真 |
-s file |
文件大于0为真 |
-S file | 是套接字文件为真 |
-t fd | |
-u file |
|
-w file |
文件可写为真 |
-x file |
文件可执行为真 |
-G file |
|
-L file |
文件为符号链接为真 |
-N file |
最后一次被读取之后修改为真 |
-O file |
|
file1 -ef file2 |
硬链接文件为真 设备号一致、节点号一致 |
file1 -nt file2 |
file1的“修改时间”更新为真 或 file1存在,file2不存在为真 |
file1 -ot file2 |
file1的“修改时间”更旧为真 或 file1不存在,file2存在为真 |
-o optname |
|
-v varname |
|
-z string |
字符串长度为零时为真 |
string -n string |
字符串长度非零时为真 |
string1 = string2 |
字符串相等时为真 |
string1 != string2 |
字符串不相等时为真 |
string1 < string2 |
strring1排序在前时为真 |
string1 > string2 |
|
int1 -eq int2 |
数字相等 |
int1 -ge int2 |
大于等于 |
int1 -gt int2 | 大于 |
int1 -le int2 | 小于等于 |
int1 -lt int2 | 小于 |
int1 -ne int2 | 数字不等 |
EXPR1 -a EXPR2 |
与关系 |
EXPR1 -o EXPR2 | 或关系 |
! EXPR | 取反 |
======================================================
例子:字符串长度“非零”为真
[view@payqa2 ~]$ string="" [view@payqa2 ~]$ [ $string ] && echo "true" [view@payqa2 ~]$ string="hello" [view@payqa2 ~]$ [ $string ] && echo "true" true