我对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本身。 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而不是“空白命令的退出代码”。