双方括号[[]]的用法:
1、先举个例子说明:
假如你要再判断某个目录是否存在,又想当然写成:
$ [ -f exists.txt && -d exists_folder ]; echo $? bash: [: missing `]' 2
结果提示漏了右括号,那是因为 &&
被 bash 预先解析了,而不是当成 test 的参数传递。
-
&&
表示如果左边的命令正常执行了,那么继续执行右边的命令,相当于没有 else 部分的 if 语句简化版。 -
而
||
表示如果左边的命令不是正常执行了,那么继续执行右边的命令,相当于没有 then 部分的 if 语句(或者 if not)。
从效果看也可以分别当成逻辑与和逻辑或的。
所以上面那条命令以 [ -f exists.txt
明显是个不完整命令,漏了个 [
。
修正如下:
$ [ -f exists.txt ] && [ -d exists_folder ]; echo $? 0
换回一般写法也应该是:
$ test -f exists.txt && test -d exists_folder; echo $? 0
好的,到了这里开始引入正题:
2、上面我们用 [ -f exists.txt && -d exists_folder ]
来表示复合条件,结果发现这是一个坑,于是 bash 后来从 ksh 抄来一个特性来填这个坑。
把单括号换成双括号就 OK 了:
$ [[ -f exists.txt && -d exists_folder ]]; echo $? 0
震惊之情溢于言表,&&
不是隔开两个命令么,怎么用两个方括号又合法了?
前面说说单方括号是语法糖,因为只是 test 命令的另一种写法,bash 最后会调用程序 test,一般就是 /usr/bin/test。
双方括号是「关键词」,关键词就是 bash 自己内建的语法分析:
[root@noi ~]# type [[
[[ is a shell keyword
就因为这是关键词,所以被双方括号包围的代码都有另外一种意义,||
、<
这些符号的意义都被改变了,就和其它编程语言的用法一样了。
例如再比较大小时,对 >
不再需要转义了:
[root@noi ~]# [[ 3 > 1 ]];echo $? 0
但依然是表示按字符串比较,不是按数字:
[root@noi ~]# [[ 3 < 10 ]];echo $? 1
可以看作增强版的 test,因为逻辑与和逻辑或已经可以直接用 ||
,所以 -o
就不能用了,其余的参数和 test 基本一样。
因为可以使用&&和||等逻辑运算符,比较数字以外的运算推荐使用双方括号[[]]。比如上文中的:
$ [[ -f exists.txt && -d exists_folder ]]; echo $? 0
这时,如果我就想比较数字,有两种方案:
第一种:使用-gt、-lt、-ge、-le等等符号:
[root@noi ~]# [[ 3 -lt 10 ]];echo $? 0
第二种:使用双小括号:
#使用双小括号,字符之间不用空格隔开 [root@noi ~]# ((3<10));echo $? 0
3、[[]]还可以用 =~
来检查是否匹配正则,简单的就不用劳烦 grep 了:
[root@noi ~]# [[ abc =~ a ]];echo $? 0 [root@noi ~]# [[ hello =~ hell? ]];echo $? 0 [root@noi ~]# [[ hello =~ hel00? ]];echo $? 1
本节结束,请看后续双小括号闪亮登场。