Bash中的单方括号和双方括号有什么区别?
我正在阅读关于if
示例,但是一些示例是用单个方括号写的:
if [ -f $param ] then #... fi
其他与双方括号:
if [[ $? -ne 0 ]] then start looking for errors in yourlog fi
有什么区别?
Single []
是符合posixshell的条件testing。
Double [[]]
是标准[]
的扩展,受bash和其他shell支持(例如zsh,ksh)。 他们支持额外的操作(以及标准的posix操作)。 例如: ||
而不是-o
和正则expression式匹配=~
。 关于条件结构的bash手册部分可以find更多的差异列表。
每当你希望你的脚本可以在shell中移植时使用[]
。 如果您想要[]
不支持的条件expression式,请使用[[]]
,并且不需要是可移植的。
Bash上的一些差异4.3.11:
-
POSIX vs Bash扩展:
-
[
是POSIX -
[[
是一个Bash扩展
-
-
常规命令vs魔法
-
[
只是一个奇怪的名字的常规命令。]
只是一个阻止进一步论证被使用的论点。Ubuntu 16.04在
/usr/bin/[
coreutils提供了一个可执行文件,但是bash内置版本优先。Bashparsing命令的方式没有任何改变。
特别是,
<
是redirect,&&
和||
连接多个命令,( )
生成子壳除非被\
转义,并且字扩展像往常一样发生。 -
[[ X ]]
是一个单独的构造,使得神奇地被parsing。<
,&&
,||
和()
是专门处理的,分词的规则是不一样的。还有更多的差异,如
=
和=~
。
-
-
<
-
[[ a < b ]]
:词典对比 -
[ a \< b ]
:同上。\
所需或否则redirect像任何其他命令。 Bash扩展。 - 我找不到POSIX的替代scheme,请参阅: 如何testingstring小于或等于?
-
-
&&
和||
-
[[ a = a && b = b ]]
:真,逻辑和 -
[ a = a && b = b ]
:语法错误,&&
parsing为AND命令分隔符cmd1 && cmd2
-
[ a = a -ab = b ]
:相当于POSIX,但不推荐使用 -
[ a = a ] && [ b = b ]
:POSIXbuild议
-
-
(
-
[[ (a = a || a = b) && a = b ]]
:假 -
[ ( a = a ) ]
:语法错误,()
被解释为一个子shell -
[ \( a = a -oa = b \) -aa = b ]
:等价,但()
被POSIX弃用 -
([ a = a ] || [ a = b ]) && [ a = b ]
POSIXbuild议
-
-
分词
-
x='a b'; [[ $x = 'ab' ]]
x='a b'; [[ $x = 'ab' ]]
:真,引号不需要 -
x='a b'; [ $x = 'ab' ]
x='a b'; [ $x = 'ab' ]
:语法错误,展开为[ ab = 'ab' ]
-
x='a b'; [ "$x" = 'ab' ]
x='a b'; [ "$x" = 'ab' ]
:相当于
-
-
=
-
[[ ab = a? ]]
[[ ab = a? ]]
:true,因为它做模式匹配 (* ? [
是魔术)。 不会扩展到当前目录中的文件。 -
[ ab = a? ]
[ ab = a? ]
:a?
glob扩展。 所以根据当前目录中的文件可能是真或假。 -
[ ab = a\? ]
[ ab = a\? ]
:false,不是glob扩展 -
=
和==
在[
和[[
中是相同的,但==
是Bash扩展名。 -
printf 'ab' | grep -Eq 'a.'
:相当于POSIX ERE -
[[ ab =~ 'ab?' ]]
[[ ab =~ 'ab?' ]]
:假,用''
丢失魔法 -
[[ ab? =~ 'ab?' ]]
[[ ab? =~ 'ab?' ]]
:是
-
-
=~
-
[[ ab =~ ab? ]]
[[ ab =~ ab? ]]
:true,POSIX 扩展正则expression式匹配,?
不扩展 -
[ a =~ a ]
:语法错误。 没有bash等价物。 -
printf 'ab' | grep -Eq 'ab?'
:相当于POSIX
-
build议 :始终使用[]
。
对于我所见过的每个[[ ]]
结构都有POSIX等价物。
如果你使用[[ ]]
你:
- 失去可移植性
- 迫使读者了解另一个bash扩展的复杂性。
[
只是一个带有奇怪名字的常规命令,不涉及特殊的语义。
在条件testing(即[…])的单个括号内,一些操作符(如single =
)被所有的shell支持,而一些旧的shell不支持使用operator ==
。
在条件testing的双括号内(即[[…]]),在旧的或新的shell中使用=
或==
没有区别。
编辑:我也应该注意到:在bash中,如果可能,总是使用双括号[[…]],因为它比单个括号更安全。 我将用下面的例子来说明为什么:
if [ $var == "hello" ]; then
如果$ var恰好为null / empty,那么这就是脚本所看到的:
if [ == "hello" ]; then
这将打破你的脚本。 解决方法是使用双括号,或者始终记住要在variables( "$var"
)中加引号。 双括号是更好的防守编码练习。
[[
是一个bash关键字类似于(但比它更强大) [
命令。 见http://mywiki.wooledge.org/BashFAQ/031和http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
除非你正在写POSIX sh,否则我们推荐[[
你可以使用双方括号来进行轻型正则expression式匹配,例如:
if [[ $1 =~ "foo.*bar" ]] ; then
(只要你使用的bash版本支持这种语法)
Bash手册说:
与[[,'<'和'>'运算符一起使用按照字典顺序使用当前语言环境进行sorting。 testing命令使用ASCIIsorting。
(testing命令与[]相同)