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命令与[]相同)