我只是想知道究竟有什么区别
[[ $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
,用双括号进行比较,我们可以使用==
, !=
, <,
和>
字面意思。