在bash中使用双括号执行命令无法生效

5

为了保持一致性,我尝试在所有的if语句中使用双括号[[ ]]. 但当我想要检查运行命令的返回值时,遇到了问题。经过多次测试if语句的创建方式,我发现只有不用括号才能执行命令。

以下代码不起作用:

if [[ $command ]] ; then
    echo "something"
fi

if [[ $(command) ]] ; then
    echo "something"
fi

if [[ ${command} ]] ; then
    echo "something"
fi

以上代码即使命令未运行,也使if循环为真。 由于上述代码不适用于大括号,因此使用以下内容也无效:

[[ $command ]] || echo "failed"

并且它也不能在子shell中工作。

以下内容可以正常工作:

if $command ; then
    echo "something"
fi

if $(command) ; then
    echo "something"
fi

为什么在if循环中使用括号放置命令无法正常工作?为什么上面的if循环报告为true,即使它没有运行命令?我使用的是bash版本4.1.9。我已经尝试过很多次,if循环和我上面输入的一样简单,它只是检查命令是否成功运行,如果没有则退出。

你尝试过使用 if [[ \$command`]]` 吗? - Ashish Gaur
这对我不起作用,if循环也返回false。它看起来也不好,似乎也不是推荐的方法。而且我不明白为什么它可以在没有[[ ]]的情况下工作,但是有[[ ]]时却不能工作...难道[[ ]]不应该是bash的扩展吗?所以它应该能够工作。 - user2959896
双括号是调用“test”的快捷方式。使用“man test”查找详细信息。如果您想测试程序的退出状态,则使用“if someProgram; then echo“它起作用了!”; fi”,这将完美地工作,您不需要双括号。这取决于您正在做什么。 - scott_fakename
3个回答

6

简短回答:

  • [[[ 期望是一个表达式

  • if 期望是一个命令

换句话说:

[[ $(command) ]]

会执行以下内容:

[[ -n <command_output> ]]

这可能是您想要的,也可能不是您想要的。另一方面,说:

$command && echo something || echo other

根据命令的返回代码(0代表成功,非零则表示失败),会回显something或者other


1
话虽如此,如果“工作”意味着command写入标准输出,则if [[ $(command) ]]起作用 - kojiro
嗯,好的,但如果 [[ $(command) ]] 对我不起作用,我只是像普通命令一样执行它,而默认情况下是将命令的输出写入标准输出,对吧? - user2959896
没有默认行为。某些命令会将输出写入标准输出,而有些则不会。 - kojiro
好的,谢谢您非常快速的回答。我一直在阅读Bash手册,但我不记得或看到您所写的内容在那里有解释。 - user2959896
@user2959896 你应该在手册中看到这个。你也可以通过输入 help [[ 或者 help if 来查看一些相关信息。 - devnull

3
如果您只是检查命令的返回值,请删除双括号。
if $command
then
    echo "Command succeeded"
else
    echo "Command failed: $!"
fi

双括号是一个测试命令。 (实际上并不是,但它们是单方括号的变体,而单方括号是对 test 命令的别名。) 在早期的 Bourne shell 中,你会看到像这样的东西:
if test -z "$string"
then
    echo "This is an empty string"
fi

方括号是语法糖:
if [ -z "$string" ]
then
    echo "This is an empty string"
fi

因此,如果您不进行实际测试,则可以消除双方括号或单方括号。

如果您使用方括号,则应使用双方括号而不是单方括号,因为双方括号更加宽容并且可以执行更多操作:

if [ -z $string ]    #  No quotes: This will actually fail if string is zero bytes!

if [[ -z $string ]]  #  This will work despite the lack of quotes

2

双括号是对test的一种快捷方式。在你的例子中,发生的是你正在测试shell变量$command是否存在。

if [[ $PWD ]]; then
    echo PWD is set to a value
fi

if [[ $NOT_A_REAL_VAR ]]; then
    echo Nope, its not set
fi

在您提供的第二个例子中,您使用命令替换来检查command是否在标准输出上输出了一些内容。
if [[ $(echo hi) ]]; then
    echo "echo said hi'
fi

if [[ $(true) ]]; then #true is a program that just quits with successful exit status
    echo "This shouldn't execute"
fi

您的第三个例子与第一个例子基本相同。如果您想分组变量,则可以使用花括号,例如,如果您想在某些内容后面添加“s”。

WORD=Bike
echo "$WORDS" #won't work because "WORDS" isn't a variable
echo "${WORD}S" # will output "BikeS"

然后在你的第五个示例中,你正在运行位于 command 中的程序。

因此,如果你想测试一些字符串,请使用[[ ]]或[ ]。如果你只想测试程序的退出状态,则不要使用它们,只需使用裸的if语句即可。

有关括号的详细信息,请查看man test


1
我意识到可以通过 [[ $(false; echo -n $?) == 1 ]][[ $(true; echo -n $?) == 0 ]] 来测试程序的退出状态。很棒! - CMCDragonkai

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