##
# 本文为《shell脚本专家指南》一书的学习笔记。
##
4. 比较和测试
通用形式
if [ "$string" = "some_string" ]; then ...
if [ $integer -eq 15 ]; then ...
注意双引号 "" 的使用,原文说明比较模糊,后来我做了测试。
在test 和 [] 中,如果$a中a未定义,不加双引号,会导致报错
"unary operator expected",在[[]]中,没有此限制。
同样的,如果$a中a存在空格, 那么在test和[]中,不加""会导致报错
"too many arguments",在[[]]中,没有此限制。
个人建议,对于字符串变量名和显式字符串,均采用""进行引用,数字
不用""进行引用。因此,个人认为,通用形式可以表示为
if [ "$string" = "some_string" ]; then ...
if [ "$integer" -eq 15 ]; then ...
关于字符串比较运算符 = != > < 和数字比较运算符 -eq -ne -gt -lt 互相对应。
其中-eq等只能操作数字,=等可以操作数字和字符串。
另外注意,在test和[]中,字符串比较不能使用>和<,因为两者均返回true,
而在[[]]中,>和<可以正常使用。
[] 和 test 可以互相替换使用,比如
if [ "$a" = "a" ]; then ...
if test "$a" = "a"; then ...
if/then 的一种替换形式。
if [ "$a" = "a" ]; then echo ok; fi
可替换为
test "$a" = "a" && echo ok # [ "$a" = "a" ] && echo ok
多行语句替换
if [ "$a" = "a" ]; then echo ok; echo good;fi
可替换为
test "$a" = "a" && {
echo ok
echo good
}
# [ "$a" = "a" ] && {
# echo ok
# echo good
# }
替换原理,&&连接的语句,只有当前部分为真时,后部分才会执行。
同理,||连接的语句,只有当前部分为假时,后部分才会执行。
多级判断
# 当txt变量不为空,且txt与txt2不同时,为var赋值"$txt $txt2"
[ "$txt" ] && [ "$txt" != "$txt2" ] && var="$txt $txt2"
# 当txt不等于txt2且num等于num2,或者num2等于100时,执行...
if [ "$txt" != "$txt2" -a $num -eq $num2 ] || [ $num2 -eq 100 ]; then ...
如变量已定义,则...
# 此处$string必加引号,如不加引号,则-n判断始终为真。
# 不加引号时,对于空变量,会变为[ -n ] ,将-n直接看做了字符串,而非运算符。
# 不加引号的情况下,如果string变量有空格,也会报错。
if [ -n "$string" ]; then ...
if [ "$string" ]; then ...
如变量未定义,则...
# 同理,此处$string也比加引号,否则如果string变量有空格,也会报错。
if [ -z "$string" ]; then ...
if [ ! "$string" ]; then ...
示例,判断/etc/hosts是否有nodename字样。
if [ "`grep nodename /etc/hosts`" ]; then ...
if命令不仅可以判断变量和数值,还可以判断命令的返回值。
# 判断ping nodename -c 3的返回值。
if ping nodemana -c 3 > /dev/null 2>&1; then ...
test -l的特殊例子
# 判断"hello"字符串长度是否大于4。
# 下面的语句会报错。
test -l "hello" -gt 4 && echo ok
# 下面的句子正常。
/usr/bin/test -l "hello" -gt 4 && ok
原文给出的说法,bash和ksh中有内部的test指令,且不支持-l参数。
只有指定了test的全路径,才会用系统的test命令,可以支持-l参数。
# 说的云里雾绕的,which test,显示的也是系统的test路径。
# 具体原因不清楚,这点记住就好。