bash中的双方括号和单方括号有什么区别?

我只是想知道究竟有什么区别

[[ $STRING != foo ]] 

 [ $STRING != foo ] 

除了后者是符合posix的,在sh中find,前者是bash中的扩展。

    有几个区别。 在我看来,一些最重要的是:

    1. 在Bash和许多其他现代炮弹中是内build的。 内build[类似于closures的附加要求的testing] 。 内build函数[并testing模仿function/bin/[/bin/test以及它们的限制,以便脚本可以向后兼容。 原始的可执行文件仍然主要用于POSIX合规性和向后兼容性。 运行命令type [在Bash中表示[默认情况下将[解释为内置命令]。 (注意: which [只查找PATH上的可执行文件,相当于type -P [
    2. [[不是那么兼容,一般不会用任何/bin/sh指向。 所以[[是更现代的bash / zsh / korn选项。
    3. 由于[[内build于shell并且没有传统要求,因此您不必担心基于IFSvariables的单词分割,从而导致variables评估为带空格的string。 因此,你并不需要把variables放在双引号中。

    其余的只是一些更好的语法。 要看到更多的差异,我推荐这个链接到一个常见问题答案: testing,[和[[? 。 事实上,如果您认真对待bash脚本,我build议阅读整个wiki ,包括FAQ, 陷阱和指南。 指南部分的testing部分也解释了这些差异,以及为什么作者认为[[如果您不需要担心便携,是一个更好的select。 主要原因是:

    1. 您不必担心引用testing的左侧,以便将其实际读为variables。
    2. 你不必为了避免inputredirect而使用反斜杠小于和大于< > ,这样可以通过写入文件真正搞乱一些东西。 这又回到[[是一个内build的。 如果[(test)是一个外部程序,那么只有当/bin/test被调用时,shell才会评估<>的方式发生exception,这是没有意义的。

    简而言之:

    []是bash Builtins

    [[]]是bash 关键字

    关键词:关键词与内置关键词相似,但主要区别在于特殊的分析规则适用于它们。 例如,[是一个bash内build的,而[[是一个bash关键字。 他们都用于testing的东西,但由于[是一个关键字,而不是一个内置的,它受益于一些特殊的分析规则,使它更容易:

      $ [ a < b ] -bash: b: No such file or directory $ [[ a < b ]] 

    第一个例子返回一个错误,因为bash试图将文件bredirect到命令[a]。 第二个例子实际上是你所期望的。 字符<不再具有文件redirect操作符的特殊含义。

    来源: http : //mywiki.wooledge.org/BashGuide/CommandsAndArguments

    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,请参阅: https : //stackoverflow.com/questions/21294867/how-to-test-strings-for-less-than-or-equal
    • &&||

      • [[ 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扩展的复杂性。 [只是一个带有奇怪名字的常规命令,不涉及特殊的语义。

    根据对联机帮助页相关部分的快速阅读,主要区别似乎是==!=运算符与模式匹配,而不是字面string,并且还有=~正则expression式比较运算符。

    单支架[]是POSIXshell兼容以包含一个条件expression式。

    双括号 ie [[]]是标准POSIX版本的增强版(或扩展版),这是由bash和其他shell(zsh,ksh)支持的。

    在bash中,对于数字比较,我们使用eqneltgt ,用双括号进行比较,我们可以使用==!=<,>字面意思。