Answers:
[[ … ]]和之间的区别[ … ]主要在于使用单括号或双括号bash。至关重要的是,它[[ … ]]是特殊的语法,而它[是命令的一个好看的名称。[[ … ]]对于里面的东西有特殊的语法规则[ … ]。
随着通配符的增加,下面[[ $a == z* ]]是评估方法:
[[ … ]]围绕条件表达式的条件构造$a == z*。==二进制运算符,其操作数$a和z*。a。==运算符:测试变量的值是否a与pattern匹配z*。下面是如何[ $a == z* ]进行评估:
[与通过评估的话形成的参数命令$a,==,z*,]。$a为变量的值a。a是6个字符的字符串foo b*(由例如获得a='foo b*')和文件的在当前目录(列表bar,baz,qux,zim,zum),则扩展的结果是下列词语的列表:[,foo,bar,baz,==,zim,zum,]。[使用上一步中获得的参数运行命令。
[命令抱怨语法错误并返回状态2。注意:在[[ $a == z* ]]的第3步中,的值a不会进行单词拆分和文件名生成,因为它是在需要单个单词的上下文中(条件运算符的左侧参数==)。在大多数情况下,如果单个单词在该位置有意义,那么变量扩展的行为就像在双引号中一样。但是,该规则有一个例外:在中[[ abc == $a ]],如果的值a包含通配符,则a与通配符模式匹配。例如,如果值a是a*则[[ abc == $a ]]是真(因为通配符*从的无引号膨胀来$a匹配*),而[[ abc == "$a" ]]是假的(因为普通字符*来自引用的扩展名$a不匹配bc)。内[[ … ]],双引号不有所作为,除了在字符串匹配运营商的右手边(=,==,!=和=~)。
[是test命令的别名。Unix版本6有一个if命令,但是版本7(1979)带有新的Bourne shell,它具有一些编程结构,包括if-then-else-elif-fi结构,而Unix 7添加了一个test执行大多数命令的命令。if在较旧版本中由命令执行的“测试” 。
[是testUnix System III(1981)的别名,并且两者都内置在Shell中。尽管应该指出的是,某些Unix变体[直到此之后才有命令(直到2000年代早期,某些sh基于Almquist shell的BSD上才有命令(test内置ash源始终包含在s中,但是基于最初被禁用的BSD))。
请注意,testaka [是执行“测试”的命令,没有该命令执行的赋值,因此没有理由在赋值和相等运算符之间进行歧义,因此相等运算符为=。==仅受到的一些最新实现的支持[(并且只是的别名=)。
因为[只不过是一个命令,所以外壳程序会以与其他任何命令相同的方式来解析它。
具体来说,在您的示例中$a,由于未加引号,因此将根据常规的单词拆分规则将其拆分为多个单词,并且每个单词都将进行文件名生成(也称为“ globbing”),以产生可能更多的单词,每个单词导致[命令的单独参数。
同样,z*将扩展到当前目录中以开头的文件名列表z。
因此,举例来说,如果$a是b* = x,有z1,z2,b1以及b2文件在当前目录中,该[命令将获得9个参数:[,b1,b2,=,x,==,z1,z2和]。
[将其参数解析为条件表达式。这9个参数未加起来为有效的条件表达式,因此可能会返回错误。
该[[ ... ]]构造体是Korn壳大约在1988年引入的,因为ksh86a1987年ksh88从一开始就没有这种构造。
除了ksh(所有实现)之外,[[...]]bash(自2.02版起)和zsh也支持bsh(从2.02版开始),但是这三个实现都是不同的,并且同一外壳程序的每个版本之间都存在差异,尽管更改通常是向后兼容的(bash的例外是一个明显的例外)=~已知其行为发生变化时会在某个版本后破坏几个脚本的运算符)。[[...]]未由POSIX,Unix或Linux(LSB)指定。已经考虑了几次包含它,但由于主要外壳程序支持的通用功能已经被[命令和case-in-esac构造所涵盖,因此并未包括在内。
整个[[ ... ]]结构组成一个命令。也就是说,它具有退出状态(这是它最重要的资产,因为它是评估条件表达式的结果),您可以将其通过管道传递给另一个命令(尽管它没有用),并且通常可以在任何需要的地方使用它使用任何其他命令(仅在shell内部,因为它是shell构造),但它不会像普通的简单命令一样被解析。外壳将内部内容解析为条件表达式,而分词和文件名生成的通常规则也有所不同。
[[ ... ]]==从一开始就知道并等于=1。尽管ksh的一个错误(并引起混乱和许多错误)是=和==不是一个相等运算符,而是一个模式匹配运算符(尽管可以用引号禁用匹配方面,但是使用因外壳而异的不清楚规则)。
在上面的代码中[[ $a == z* ]],shell将按照与常规规则类似的规则将其解析为多个标记,将其识别为模式匹配比较,将其z*视为与a变量内容匹配的模式。
通常,[[ ... ]]用[命令比用命令射击更难。但是一些规则,例如
-aor -o运算符(使用几个[命令以及&&and和|| shell运算符)[使用POSIX shell 使其可靠。
[[...]]在不同的shell中支持额外的运算符,例如-ntregexp匹配运算符...,但列表和行为因shell而异,因版本而异。
因此,除非您知道脚本将解释哪种shell和最低版本,否则使用标准[命令可能更安全。
1个例外:[[...]]在版本中已添加到bash中2.02。在2.03更改之前,[[ x = '?' ]]返回true,而[[ x == '?' ]]返回false。引用并不能阻止=在那些版本中使用运算符时的模式匹配,但在使用时却可以==。
[ '!' = foo -o a = a ]在bash为实例。
两者都用于评估表达式,并且[[不适用于POSIX旧版本的bourn shell,并且[[也支持模式匹配和正则表达式。例子试试这些
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]仅在某些shell的某些版本中[支持正则表达式,就像某些版本的do支持regexp匹配一样。对于arithemtic相比之下,在那些炮弹的支持[[,你宁愿写(( n == 0 && y == 0))