我只是想知道究竟有什么区别
[[ $STRING != foo ]]
和
[ $STRING != foo ]
除了后者是符合posix的,在sh中find,前者是bash中的扩展。
有几个区别。 在我看来,一些最重要的是:
[类似于closures的附加要求的testing] 。 内build函数[并testing模仿function/bin/[和/bin/test以及它们的限制,以便脚本可以向后兼容。 原始的可执行文件仍然主要用于POSIX合规性和向后兼容性。 运行命令type [在Bash中表示[默认情况下将[解释为内置命令]。 (注意: which [只查找PATH上的可执行文件,相当于type -P [ ) [[不是那么兼容,一般不会用任何/bin/sh指向。 所以[[是更现代的bash / zsh / korn选项。 [[内build于shell并且没有传统要求,因此您不必担心基于IFSvariables的单词分割,从而导致variables评估为带空格的string。 因此,你并不需要把variables放在双引号中。 其余的只是一些更好的语法。 要看到更多的差异,我推荐这个链接到一个常见问题答案: testing,[和[[? 。 事实上,如果您认真对待bash脚本,我build议阅读整个wiki ,包括FAQ, 陷阱和指南。 指南部分的testing部分也解释了这些差异,以及为什么作者认为[[如果您不需要担心便携,是一个更好的select。 主要原因是:
< > ,这样可以通过写入文件真正搞乱一些东西。 这又回到[[是一个内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扩展。 &&和||
[[ 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等价物。
如果你使用[[ ]]你:
[只是一个带有奇怪名字的常规命令,不涉及特殊的语义。 根据对联机帮助页相关部分的快速阅读,主要区别似乎是==和!=运算符与模式匹配,而不是字面string,并且还有=~正则expression式比较运算符。
单支架即[]是POSIXshell兼容以包含一个条件expression式。
双括号 ie [[]]是标准POSIX版本的增强版(或扩展版),这是由bash和其他shell(zsh,ksh)支持的。
在bash中,对于数字比较,我们使用eq , ne , lt和gt ,用双括号进行比较,我们可以使用== , != , <,和>字面意思。