Shell脚本的表达式
本篇包含的内容:
- 三种条件测试表达式
- 文件测试表达式及操作符
- 字符串测试表达式及操作符
- 整数二元比较操作符
- 逻辑操作符
条件测试表达式
test < 表达式 >
[ < 表达式 > ]
[[ < 表达式 > ]]
((< 表达式 >))
在[[]]
(双中括号)中可以使用通配符等进行模式匹配,这是其区别于其他几种语法格式的地方
&&
、||
、>
、<
等操作符可以应用于[[]]
中,但不能应用于[]
中,在[]
中一般用-a
、-o
、-gt
(用于整数)、-lt
(用于整数)代替上述操作符。
test < 表达式 >
[root@localhost shell]# test -f file && echo true || echo false
false
该语句表示如果file文件存在,则输出true,否则(||)输出false。这里的&&是并且的意思。test的-f参数用于测试文件是否为普通文件,test命令若执行成功(为真),则执行&&后面的命令,而||后面的命令是test命令执行失败之后(为假)所执行的命令。
[root@localhost shell]# ls -l *.log
-rw-r--r-- 1 root root 17 3月 5 11:08 grep.log
-rw-r--r-- 1 root root 17 3月 5 14:20 sed.log
[root@localhost shell]# test -f grep.log && echo true || echo false
true
[root@localhost shell]#
提示:关于test测试表达式的更多知识可执行man test查看帮助
[ < 表达式 > ]
注意:中括号内部的两端要有空格,[]和test等价,即test的所有判断选项都可以直接在[]里使用。
[root@localhost shell]# [ -f grep.log ] && echo 1 || echo 0
1
[root@localhost shell]#
[[ < 表达式 > ]]
[root@localhost shell]# [[ -f grep.log ]] && echo 1 || echo 0
1
文件测试表达式
下面的操作符号对于[[]]
和[]
和test
的测试表达式通用
-d 文件
:判断文件目录是否存在-f 文件
:判断文件是否存在-e 文件
:判断文件或目录是否存在-r 文件
:判断文件是否存在且可读-s 文件
:判断文件存在且大小不为0-w 文件
:判断文件存在且可写-x 文件
:判断文件存在且可执行-L 文件
:判断文件存在且为链接文件f1 -nt f2
:判断文件f1比文件f2新f1 -ot f2
:判断文件f1比文件f2旧
实际使用如下:
[root@localhost shell]# touch oldboy
[root@localhost shell]# ls -l oldboy
-rw-r--r-- 1 root root 0 3月 9 17:52 oldboy
[root@localhost shell]# [ -f oldboy ] && echo 1 || echo 0
1
[root@localhost shell]# mkdir oldgirl
[root@localhost shell]# [ -f oldgirl ] && echo 1 || echo 0
0
[root@localhost shell]# [ -d oldgirl ] && echo 1 || echo 0
1
[root@localhost shell]# [ -e oldgirl ] && echo 1 || echo 0
1
[root@localhost shell]# [ -e oldboy ] && echo 1 || echo 0
1
[root@localhost shell]# [ -d oldboy ] && echo 1 || echo 0
0
[root@localhost shell]#
[root@localhost shell]# [ -r oldboy ] && echo 1 || echo 0
1
[root@localhost shell]# [ -w oldboy ] && echo 1 || echo 0
1
[root@localhost shell]# [ -x oldboy ] && echo 1 || echo 0
0
[root@localhost shell]# chmod 001 oldboy
[root@localhost shell]# ls -l oldboy
---------x 1 root root 0 3月 9 17:52 oldboy
[root@localhost shell]# [ -r oldboy ] && echo 1 || echo 0
1 #<===root用户特殊
[root@localhost shell]# [ -w oldboy ] && echo 1 || echo 0
1 #<===root用户特殊
[root@localhost shell]# [ -x oldboy ] && echo 1 || echo 0
1
[root@localhost shell]#
提示:测试文件的读、写、执行等属性,不光是根据文件属性rwx的标识来判断,还要看当前执行测试的用户是否真的可以按照对应的权限操作该文件。
测试Shell变量
[root@localhost shell]# file1=/etc/services;file2=/etc/rc.local
[root@localhost shell]# echo $file1
/etc/services
[root@localhost shell]# echo $file2
/etc/rc.local
[root@localhost shell]# [ -f "$file1" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -d "$file1" ] && echo 1 || echo 0
0
[root@localhost shell]# [ -s "$file1" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -e "$file1" ] && echo 1 || echo 0
1
[root@localhost shell]#
测试变量时,如果被测试的变量不加双引号,那么测试结果可能是不正确的
[root@localhost shell]# echo $oldgirl
[root@localhost shell]# [ -f $oldgirl ] && echo 1 || echo 0
1
[root@localhost shell]# [ -f "$oldgirl" ] && echo 1 || echo 0
0
[root@localhost shell]#
如果是文件实体路径,那么加引号与不加引号的结果是一样的:
[root@localhost shell]# [ -f "/etc/services" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -f /etc/services ] && echo 1 || echo 0
1
[root@localhost shell]#
字符串测试表达式
字符串测试操作符的作用包括:比较两个字符串是否相同、测试字符串的长度是否为零、字符串是否为NULL 等。
下面是字符串测试操作符:
-n "字符串"
:字符串长度不为0,则为真-z "字符串"
:字符串长度为0,则为真" 串1 " = " 串2 "
:字符串1与2相等" 串1 " != " 串2 "
:字符串1与2不相等
字符串测试操作符实践:
[root@localhost shell]# [ -n "abc" ] && echo 1 || echo 0
1
[root@localhost shell]# test -n "abc" && echo 1 || echo 0
1
[root@localhost shell]# test -n "" && echo 1 || echo 0
0
[root@localhost shell]# var="oldboy"
[root@localhost shell]# [ -n "$var" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -n $var ] && echo 1 || echo 0
1
[root@localhost shell]# [ "abc" = "abc" ] && echo 1 || echo 0
1
[root@localhost shell]# [ "abc" = "abd" ] && echo 1 || echo 0
0
[root@localhost shell]# [ "$var" = "oldboy" ] && echo 1 || echo 0
1
[root@localhost shell]# [ "$var" == "oldboy" ] && echo 1 || echo 0
1
[root@localhost shell]# [ "$var" != "oldboy" ] && echo 1 || echo 0
0
[root@localhost shell]#
若字符串进行比较时,操作符两端没有空格,如下:明显不带空格的出错了
[root@localhost shell]# [ "abc"="1" ] && echo 1 || echo 0
1
[root@localhost shell]# [ "abc" = "1" ] && echo 1 || echo 0
0
[root@localhost shell]
字符串在条件测试表达式中不加引号带来的问题:字符串不加双引号,可能会导致判断上出现逻辑错误
[root@localhost shell]# var=""
[root@localhost shell]# [ -n "$var" ] && echo 1 || echo 0
0
[root@localhost shell]# [ -n $var ] && echo 1 || echo 0
1
[root@localhost shell]# [ -z "$var" ] && echo 1 || echo 0
1
[root@localhost shell]#
总结:在条件测试表达式中,shell变量要用""包裹。字符串测试操作符两端要有空格。
整数二元比较操作符
在[]
和test
中使用的比较符号
-eq
:equal-ne
:not equal-gt
:greater than-ge
:greater equal-lt
:less then-le
:less equal
在(())
和[[]]
中使用的比较符号
==或=
!=
>
>=
<
<=
实践:
[root@localhost shell]# [ 2 -gt 1 ] && echo 1 || echo 0
1
[root@localhost shell]# [ 2 -ge 1 ] && echo 1 || echo 0
1
[root@localhost shell]# [ 2 -le 1 ] && echo 1 || echo 0
0
[root@localhost shell]# [ 2 -le 1 ] && echo 1 || echo 0
0
[root@localhost shell]#
有关[]、[[]]、(())用法的小结:
- 整数加双引号的比较是对的
- []]中用类似-eq等的写法是对的,[[]]中用类似>、<的写法也可能不对,有可能会只比较第一位,逻辑结果不对。
- []中用类似>、<的写法在语法上虽然可能没错,但逻辑结果不对,可以使用=、! =正确比较。
- (())中不能使用类似-eq等的写法,可以使用类似>、<的写法
变量使用比较操作符:
[root@localhost shell]# a1=98;a2=99
[root@localhost shell]# [ $a1 -eq $a2 ] && echo 1 || echo 0
0
[root@localhost shell]# [ "$a1" -eq "$a2" ] && echo 1 || echo 0
0
[root@localhost shell]# [ "$a1" -gt "$a2" ] && echo 1 || echo 0
0
[root@localhost shell]# [ "$a1" -lt "$a2" ] && echo 1 || echo 0
1
[root@localhost shell]#
逻辑操作符
在[]
和test
中使用的逻辑操作符号:
-a
-o
!
在[[]]
和(())
中使用的逻辑操作符号:
&&
||
!
实践:
[root@localhost shell]# [ -f /etc/hosts -a -f /etc/services ] && echo 1 || echo 0
1
[root@localhost shell]# [[ -f /etc/hosts && -f /etc/services ]] && echo 1 || echo 0
1
[root@localhost shell]#
配合文件测试表达式使用:
[root@localhost shell]# f1=/etc/rc.local ;f2=/etc/services
[root@localhost shell]# echo -ne "$f1 $f2
"
/etc/rc.local /etc/services
[root@localhost shell]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -f "$f1" -o -f "$f22" ] && echo 1 || echo 0
1
[root@localhost shell]# [ -f "$f11" -o -f "$f22" ] && echo 1 || echo 0
0
[root@localhost shell]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0
-bash: [: 缺少 `]'
0
[root@localhost shell]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0
1
[root@localhost shell]#
配合字符串测试表达式
[root@localhost shell]# a="oldboy";b="oldgirl"
[root@localhost shell]# echo -ne "$a $b
"
oldboy oldgirl
[root@localhost shell]# [[ ! -n "$a" && ! -n "$b" ]] && echo 1 || echo 0
0
[root@localhost shell]# [[ -n "$a" && -n "$b" ]] && echo 1 || echo 0
1
[root@localhost shell]# [[ -z "$a" || "$a" != "$b" ]] && echo 1 || echo 0
1
[root@localhost shell]# [[ ! -n "$a" && "$a" = "$b" ]] && echo 1 || echo 0
0
[root@localhost shell]# [[ -z "$a" -o "$a" != "$b" ]] && echo 1 || echo 0
-bash: 条件表达式中有语法错误
-bash: `-o' 附近有语法错误
使用二元比较操作符
[root@localhost shell]# m=21;n=38
[root@localhost shell]# (( m>20 && n>30 )) && echo 1 || echo 0
1
[root@localhost shell]# (( m<20 || n>30 )) && echo 1 || echo 0
1
[root@localhost shell]# (( m<20 || n<30 )) && echo 1 || echo 0
0
[root@localhost shell]# (( m<20 -a n<30 )) && echo 1 || echo 0
-bash: ((: m<20 -a n<30 : 表达式中有语法错误 (错误符号是 "n<30 ")
0
[root@localhost shell]#
实践:
[root@localhost shell]# cat 6_35_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-09
#FileName: 6_35_1.sh
#Description: This is a test script.
#***********************************************
read -t 10 -p "pls input two num:" a b
[ -z "$a" -o -z "$b" ]&&{
echo "pls input two num again"
exit 1;
}
expr $a + 10 &>/dev/null
RETVAL1=$?
expr $b + 10 &>/dev/null
RETVAL2=$?
[ $RETVAL1 -eq 0 -a $RETVAL2 -eq 0 ] ||{
echo pls input num
exit 1;
}
[ "$a" -eq "$b" ] &&{
echo "$a=$b"
exit 0;
}
[ "$a" -lt "$b" ] &&{
echo "$a<$b"
exit 0;
}
[ "$a" -gt "$b" ] &&{
echo "$a>$b"
exit 0;
}
[root@localhost shell]# sh 6_35_1.sh
pls input two num:1 2
1<2
打印选择菜单,按照选择项一键安装不同的Web服务:
[root@localhost shell]# cat menu.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-09
#FileName: menu.sh
#Description: This is a test script.
#***********************************************
#<==这里cat的用法就是按指定格式打印多行文本
cat <<END
1.wangbingbing
2.panxiaoting
3.gongli
END
read -t 5 -p "which do you like?pls input the num:" a
[ "$a" = "1" ]&&{
echo "wangbingbing"
exit 0;
}
[ "$a" = "2" ]&&{
echo "panxiaoting"
exit 0;
}
[ "$a" = "3" ]&&{
echo "gongli"
exit 0;
}
#<==这里用到了[[]]的通配符匹配的用法
[[ ! "$a" = ~[1-3] ]]&&{
echo "you input error"
exit 0;
}
[root@localhost shell]# sh menu.sh
1.wangbingbing
2.panxiaoting
3.gongli
which do you like?pls input the num:1
wangbingbing
[root@localhost shell]# sh menu.sh
1.wangbingbing
2.panxiaoting
3.gongli
which do you like?pls input the num:2
panxiaoting
[root@localhost shell]# sh menu.sh
1.wangbingbing
2.panxiaoting
3.gongli
which do you like?pls input the num:3
gongli
[root@localhost shell]# sh menu.sh 4
1.wangbingbing
2.panxiaoting
3.gongli
which do you like?pls input the num:4
you input error