一位同事最近在一次代码评审中声称,在类似于

if [ "`id -nu`" = "$someuser" ] ; then
     echo "I love you madly, $someuser"
fi

他无法提供理由。有吗?


当前回答

我感到惊讶的是,我没有看到这个问题提前提出,但请考虑:

$ n=5
$ [[ $n -gt 0 ]] && echo $n is positive
5 is positive
$ n=foo
$ [[ $n -gt 0 ]] && echo $n is positive
$ [ "$n" -gt 0 ] && echo $n is positive
bash: [: foo: integer expression expected

行[[$n-gt 0]]中缺少错误消息,导致[[完全不可用。也许我太苛刻了,正确的答案是避免在[[中进行整数比较,但我强烈建议不要使用[[。

其他回答

简而言之,[[更好,因为它不会分叉另一个进程。没有括号或单括号比双括号慢,因为它分叉另一进程。

如果你喜欢遵循谷歌的风格指南:

测试、[…]和[[…]][[…]]优先于[…]、test和/usr/bin/[。[[…]]减少了错误,因为[[和]]之间不发生路径名扩展或单词分割。此外,[[…]]允许正则表达式匹配,而[…]不允许。#这确保了左侧的字符串由#后跟字符串名称的alnum字符类。#注意,此处不应引用RHS。如果[[“文件名”=~^[[:alnum:]]+名称]];然后echo“匹配”传真#这与确切的模式“f*”匹配(在这种情况下不匹配)如果[[“filename”==“f*”]];然后echo“匹配”传真#当f*扩展到#当前目录的内容如果[“filename”==f*];然后echo“匹配”传真有关血腥的详细信息,请参见E14http://tiswww.case.edu/php/chet/bash/FAQ

无法使用[[的典型情况是在autotools configure.ac脚本中。括号具有特殊和不同的含义,因此必须使用test而不是[[或[[--请注意,test和[是同一个程序。

在一个标记为“bash”的问题中,标题中明确包含“In bash”,我对所有回复都表示应该避免[[…]]感到有点惊讶,因为它只在bash中有效!

确实,可移植性是主要的反对意见:如果你想编写一个能在Bourne兼容的shell中工作的shell脚本,即使它们不是bash,您应该避免使用[[…]]。(如果您想在更严格的POSIX shell中测试shell脚本,我建议使用dash;虽然它是一个不完整的POSIX实现,因为它缺乏标准所需的国际化支持,但它也缺乏对bash、ksh、zsh等中许多非POSIX构造的大部分(但不是全部)的支持)

我看到的另一个反对意见至少适用于bash的假设:[[…]]有自己的特殊规则,您必须学习,而[…]的行为就像另一个命令。这也是事实(桑蒂利先生带来了显示所有差异的收据),但差异是好是坏还是很主观。我个人认为,双括号结构允许我使用(…)进行分组,使用&&和||进行布尔逻辑,使用<和>进行比较,以及使用未加引号的参数展开,这让我感到很自由。这就像它自己封闭的小世界,表达式的工作方式更像传统的非命令shell编程语言。

我没有提到的一点是,[[…]]的这种行为与POSIX指定的算术扩展构造$((…))的行为完全一致,并且还允许使用未加引号的括号、布尔运算符和不等式运算符(此处执行数值而不是词法比较)。本质上,无论何时看到双括号字符,都会得到相同的引号屏蔽效果。

(Bash及其现代亲属也使用((…))(不带前导$)作为循环头的C样式或执行算术运算的环境;这两种语法都不是POSIX的一部分。)

因此,有一些很好的理由选择[[…]];也有避免它的原因,这可能适用于或不适用于您的环境。至于你的同事,“我们的风格指南这么说”是一个合理的理由,但我也会从了解风格指南为什么推荐它的人那里寻找背景故事。

[[]]有更多功能-我建议您查看《高级Bash脚本指南》以了解更多信息,特别是第7章中的扩展测试命令部分。测验。

顺便说一下,正如指南所指出的,[[]]是在ksh88(1988年版的KornShell)中引入的。