1. 概念上来说

(1)"[[",是关键字,许多shell(如sh bash)并不支持这种方式。sh, bash(据说从2.02起引入对[[的支持)等支持。

(2)"["是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,"["与"test"是内部(builtin)命令,换句话说执行"test"/"["时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。


2. 相同:

(1)二者都支持算术比较和字符串比较表达式(具体使用可能有点不同)

  1. "-gt", "-lt"是算术比较操作符,用于比较整数的大小。

  2. ">", "<"是字符串比较操作符,用于比较字符串的大小,使用字典顺序,与当前的locale有关。

  • 关于字符串比较。[...]、``.``.``.``中都可以对字符串进行比较,比较的顺序是"字典顺序"。对ascii字符来讲,码表中排列在前的较小。只要用了"<"、">",就表示是字符串比较,那么9 > 100为真,因为这实际上等价于‘9’ > ‘100’,9在码表中排在1后面,所以字符串"9"大于字符串"100"。只要搞清楚了何时是算术比较,何时是串比较,一般就不会出错了。

  • 建议在使用数值比较的时候,使用let,(())命令,否则容易出错;

(2)都支持简单的模式匹配

  • * : 匹配0个或多个任意字符

  • ? : 匹配一个任意字符


3.不同

(1)逻辑与、或

  • "[":-a表示逻辑与;-o表示逻辑或;

  • "[[":&&表示逻辑与;||表示逻辑或;


4.表格展示异同

wKiom1dip8jRdL-xAAAl7O-DqfI858.png

wKioL1diqW7R5VfMAAAxgr2ll_4387.png


5.[[]]的优势:

(1)[[]]结构比Bash版本的[]更通用。

(2)在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。

(3)用` `.``.``.` `测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。

  • [ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;

wKiom1dirPagHtYLAAAf02b5sos122.png

(4)` `.``.``.` `进行算术扩展,而[ ... ]不做。


6.[[]]的劣势:

由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。

例如:在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在` `.``.``.` `则不允许这样做。


7.几个建议

(1)数字的运算可使用let、(( )) ,其中运算时不需要变量$符号。

(2)使用 (( )) 时,不需要空格分隔各值和运算符,使用 ` ` 时需要用空格分隔各值和运算符。

(3)在 bash中,数字的比较最好使用 (( ))。

虽说可以使用 ` `,但若在其内使用运算符 >、>=、<、<=、==、!= 时,其结果经常是错误的;

不过若在 ` ` 中使用 [ ] 中的运算符“-eq、-ne、-le、-lt、-gt、-ge”等,还尚未发现有错。因此诸如$ [[ " a" != “b” && 4 > 3 ]] 这类组合(见上)也不可以在bash中使用,其出错率很高。

例:[[ "a" != "b" && 10 > 2 ]] 判断结果就不正常。

诸如 [ 2 \< 10 ]、[[ 2 < 10 ]] 都是不要使用。

使用算术扩展最好用 (( 99+1 == 100 )) ,而不要使用[[ 99+1 -eq 100 ]] 。