评价bash中的反引号

我对bash中反引号的评价感到困惑。 我以前看过这样的代码是有道理的:

RESULT=`whoami` 

这将whoami命令的输出存储在RESULTvariables中,并确认反引号计算到其中的命令的输出 。 但是我也看到如下代码:

 if `wget google.com -T 2 -t 1 -o /dev/null`; then echo "Internet ok" fi 

这是testing互联网连接通过试图获得谷歌的主页(一个单一的尝试-t 1-T 2的2秒超时,并redirect到/dev/null因为它实际上并不需要输出,而只是想看看是否成功)。 该代码读取,就好像作者期望反引号将评估wget命令的退出代码而不是输出。

但它实际上工作。 它打印Internet ok如果它可以连接到google.com,如果我改变了一些废话url不存在,它不满足if语句和打印什么。 我不明白为什么这个工作。

独立运行带有效和无效URL的wget命令在这两种情况下都不会打印任何内容,只有退出代码才会有所不同。

我的结论是,有一个特殊的结构, if后面的反引号返回退出代码,而不是输出。 我错了吗?

不,反引号没有特别的含义,甚至可以在if语句中运行wget命令,而不使用它们。
if总是评估命令的退出代码。

更全面的概述可以在这里find。


编辑

反引号启动一个在子shell中执行的命令replace,并返回一个退出代码。 if只是检查返回码,它不会使用命令的输出。

要比较一个命令的输出,你可以使用[ ,必须closures] ,这基本上是一个testing。 testing可以是任何东西

  • man test
  • 一个string比较

     [ "hello" == "test" ] 
  • 一个整数testing

     [ 2 -eq 3 ] 

如果testing成功,你得到一个退出码0(真),否则不是0(假),这再次由if评估。

所以你有如下的想法。

 if [ "`wget google.com -T 2 -t 1 -o /dev/null`" == "" ] then echo "emptY" fi 

但是这样做没什么意义,因为将输出redirect到/dev/null您将始终从[ " wget google.com -T 2 -t 1 -o / dev / null " == "" ]变为true。
另一方面,检查wget命令的输出是否包含输出也不会有用,因为即使在错误的情况下,您也会得到输出,但返回的代码不同。

在bash中,如果shell脚本,这些天避免反引号,并使用命令replace$(...)语法。

它比非常模糊的反引号更清晰,并支持嵌套,这在背后是不可能的。 IE:

 command $(command two $(command three)) 

我终于通过bash邮件列表上的讨论主题得到了明确的答案。 结论如下:

  • 这里的if语句没有什么特别之处,它只是在if和then分支的基础上执行命令的退出代码。 这里出乎意料的行为反而归因于命令replace本身。
  • 反向命令(命令replace)总是评估命令的输出 ,而不是退出代码(这不是什么新东西,只是确认反引号是否在if中使用是不相关的)。
  • 基于上述两点, if `cmd` ...根据cmd退出代码运行if时, cmd什么都不写到stdout的非显而易见的原因是有一个关于shell命令执行的POSIX spec规则,说:

如果没有命令名称,但是该命令包含一个命令replace,那么该命令应该完成最后一个命令replace的退出状态。 否则,命令应该以零退出状态完成。

ref: http : //pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html

  • 所以这只是因为在cmd没有向stdout写任何东西的情况下,shell(而不是执行一个空命令)取得命令replace的退出代码( cmd本身的退出代码),并将其作为父代的退出代码返回命令 – 然后泡到if

为了更好的说明这个,请看下面的例子:

 $ `true` $ echo $? 0 $ `false` $ echo $? 1 

shell首先运行true ,它不会向stdout发送任何东西,所以生成的命令是空的。 在我所期望的空白命令的基础上,以确定性成功或失败为基础,以完整的退出代码为true而不是“空白命令的退出代码”。