比较
写shell脚本时,if判断是经常需要使用的,shell中的比较有很多中,眼花缭乱,今天把常用的比较梳理一下
[] 和test
这两个其实是等价的,都是shell 内建命令,不过linux环境本身也提供了一个test命令,这个是外部命令,不过大多数情况下,我们调用的都是内建的test
root@LAPTOP-2MOIS3PQ:/home/li# type [
[ is a shell builtin
root@LAPTOP-2MOIS3PQ:/home/li# type test
test is a shell builtin
可以看到,这两个都是内建命令,test一般使用的不多,都是用中括号,可以用来测试文件类型,文件属性,数字比较,字符串比较,首先来说下数字和字符串。
条件 | 含义 |
---|---|
int1 -eq int2 | 数字是否相等 |
int1 -ne int2 | 不等 |
int1 -gt int2 | 大于 |
int1 -lt int2 | 小于 |
int1 -ge int2 | 大于等于 |
int1 -le int2 | 小于等于 |
这个很好记,eq就是euqal, ne: not euqal, gt: greater than;lt: less than; ge: greater eqal; le: less equal.
字符串比较就可以直接使用大于号,小于号了,不能用eq这一类
[]使用的注意事项
说说使用中要注意的事项,首先 [ 本质上是一个命令,所以左右需要空格,] 也是,比较符,比较内容左右都需要空格,因为这都是 [ 命令的参数,需要空格分隔。
因为shell是弱类型语言,所以很多时候不区分类型,如
a=1
这里你可以说a是数字,也可以说是字符串,要看上下文
数字比较命令:
a=1
if [ $a -eq 1 ]
then
echo yes
fi
看到eq后,shell把1解释成了数字,一般我们都会这样用,但是:
a=1
if [ $a = 1 ]
then
echo yes
fi
在这里用来字符串比较,这么用是ok的,因为看到=后,shell把1解释成字符串。
甚至这样
a=1
if [ $a -eq "1" ]
then
echo yes
fi
写习惯了c c++一类的强类型语言肯定说这是错的,因为一个是数字,一个是字符,但在shell中,这样也ok,因为shell会将1左右的引号剔除,如:
a="1"
echo $a
1
并不会单独加引号,想要引号,还要转义:
a=\"1\"
echo $a
"1"
这么看来好像[] 中的数字比较没什么用,我用字符串比较的写法不就OK了,反正都可以解释成字符串。很多情况下确实如此,我所了解到的,一般写数字比较的时候,大家还是倾向与写eq lt这种比较符,可能是为了凸显想比较的东西含义上是数字(如果有不对的地方,请读者在评论区指正)。
甚至,我们在写数字比较,字符串比较的时候,都会故意去加引号,如
a=1
if [ "$a" -eq "1" ]
then
echo yes
fi
之所以这么做,是因为如果a没有定义,那么命令就会出错
如
unset a
[ $a -eq 1 ] && echo yes
bash: [: -eq: unary operator expected
unset取消了a的定义,所以比较就变成了
if [ -eq 1 ]
这是不符合语法的,为了这个,所以大家倾向于加上引号
同时,比较两边的运算符都要加,如果$a加了,但1没有加,而且a没有定义,还是会出错
unset a
[ "$a" -eq 1 ] && echo yes
bash: [: : integer expression expected
这是因为"$a"被替换成了"",同时因为使用了-eq,所以变量a的内容和1被解释成了数字, ""没办法跟1比较了
在数字比较的时候,要求变量a中只有0-9数字字符,如果有其他字符,就出错了
a=1w
[ "$a" -eq 1 ] && echo yes
bash: [: 1w: integer expression expected
再说 [ ] 的字符串比较,这其实跟数字比较差不多,只是比较符直接写大于号,小于号,同时,一般也会在左右比较内容上加引号,这个原因是和数字比较类似的,甚至很多时候习惯于这么写
[ "q$a" = "qcontent" ] && echo yes
这是用来比较a的内容是否是content, 但为了防止a未定义,加上了引号,同时还加了前缀字符q, 当然不加是可以的,只是经常看到这么做,原因我不是很清楚,了解的读者烦请评论区告知下:)
一般写字符串比较的时候要加引号,这是为了防止字符串中有空格,单独的空格会被认为是 [ 命令的参数。
[[ ]]
两个中括号的比较和一个中括号的比较是类似的。唯一的不同就是在字符比较是有正则的拓展,这个我一般不会用,会用其他的代替,这里不介绍了。