在Bash if语句中,何时需要使用方括号?

128
通常,我在if语句中使用方括号:
if [ "$name" = 'Bob' ]; then ...

但是,当我检查grep是否成功时,我不使用方括号:

if grep -q "$text" $file ; then ...

if 语句中,什么时候需要使用方括号?


1
单个方括号在多个shell中兼容,但其中一些,包括Bash,支持首选的双方括号。请参阅BashFAQ/031获取更多信息。还可以参见help '[' - Dennis Williamson
3个回答

188

方括号是test命令的同义词。一个if语句检查一个命令的退出状态,以决定采取哪个分支。grep -q "$text"是一个命令,但"$name" = 'Bob'不是-它只是一个表达式。test是一个命令,它接受一个表达式并对其进行评估:

if test "$name" = 'Bob'; then ...

由于方括号是test命令的代名词,因此您可以将其重写为原始语句:

if [ "$name" = 'Bob' ]; then ...

3
@chepner:为什么 if $boolean_var ; then ... 不需要括号? - Misha Moroshko
17
@misha,如果你的$boolean_var变量的值为“true”或“false”,那么它能够正常工作,因为你运行了“true”或“false”命令。 - glenn jackman
4
如果 $boolean_var 为 01,则 if $boolean_var ; then ... 不起作用,请参阅 man trueman false - derFunk
2
@derFunk:如果你刚好在$PATH中有01命令,它会起作用 - 但那将是丑陋的。 - Keith Thompson
拼写检查不喜欢括号,但可以与测试语句一起在VSCode中使用。 - johnrubythecat
然后拼写检查器出了问题。[test的标准别名。 - chepner

47
[实际上是一个命令,几乎等同于test命令。它不是shell语法的一部分。(根据不同的shell,[test都可能是内置命令,但这并不影响它们的行为,可能会影响它们的性能。) if语句执行一个命令,并在命令成功时执行then部分,如果失败则执行else部分(如果有的话)。(如果命令以状态($?) 0退出,则命令成功,如果以非零状态退出,则命令失败。)
if [ "$name" = 'Bob' ]; then ...

这个命令是:

[ "$name" = 'Bob' ]
< p > (你可以直接执行相同的命令,而不需要< code> if 。) < p > 在
if grep -q "$text" $file ; then ...

指令是什么

grep -q "$text" $file

man [man test 以获取更多信息。

注:实际上,[ 命令与 test 命令几乎等价。不同之处在于,[ 要求其最后一个参数为 ],而 test 不要求 -- 实际上并不允许(更确切地说,test 不会特殊对待 ] 参数;例如它可以是一个有效的文件名)。 (它不必实现成这样,但是一个没有匹配的 ][ 会让很多人非常紧张。)


拼写检查不喜欢括号,但在VSCode中与测试语句一起工作。 - johnrubythecat
1
@johnrubythecat:你指的“拼写检查”是什么?如果它是用来检查英文文本拼写的,那当然不会对shell语法感到满意。 - Keith Thompson
4
加一分给“紧张”这个参数。 - Timo
我认为我们都对使用Shell语法这么多年感到非常紧张。如果我看到漏掉的闭合括号,那只是“又一件事”而已。 - gbarry

11

最好理解[ ... ]语法的方式是将[视为一个程序--事实上就是这样!

看看这个例子:

~ $ ls /usr/bin/\[ 
/usr/bin/[

另一方面,你可能没有使用它的那个版本,因为 bash 还提供了 [ 作为 shell 内置。

无论如何,回答你的问题: if 执行你给定的命令并检查其返回值是否为 0。你可以使用 [ 执行其他更有趣的比较,比如字符串比较。参见 man [man bash


在bash的man手册中没有任何内容表明[是内部实现的,我认为这就是[[存在的原因。 - PhilHibbs
@PhilHibbs:我非常确定 [ 是内置的。这就是为什么 builtin [ 起作用的原因。[[[ 有所不同,它执行不同的操作。 - cha0site
1
@PhilHibbs:在bash手册的“SHELL BUILTIN COMMANDS”部分查找。test expr[ expr ]被列在一起。 - chepner
1
@PhilHibbs:另外,尝试使用 type -a [ - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接