shell编程中的$(command)和`command`有啥区别?

Posted

技术标签:

【中文标题】shell编程中的$(command)和`command`有啥区别?【英文标题】:What is the difference between $(command) and `command` in shell programming?shell编程中的$(command)和`command`有什么区别? 【发布时间】:2011-06-10 03:53:28 【问题描述】:

要将命令的输出作为变量存储在 sh/ksh/bash 中,您可以这样做

var=$(command)

var=`command`

这两种方法有什么区别?

【问题讨论】:

请看BashFAQ/082。 您将在 Git 编码指南中找到详细的嵌套问题:请参阅 my answer below。 相关:unix.stackexchange.com/questions/126927 【参考方案1】:

除了可以在命令中使用的非转义字符之外,几乎没有什么区别。您甚至可以将 `...` 命令放在 $(...) 中(反之亦然),以进行更复杂的两级深度命令替换。

对反斜杠字符/运算符的解释略有不同。除此之外,当嵌套 `...` 替换命令时,您必须使用 \, 转义内部 ` 字符,而使用 $() 替换它会自动理解嵌套。

【讨论】:

【参考方案2】:

反引号/坟墓标记已被弃用,取而代之的是$() 用于命令替换,因为$() 可以像$(echo foo$(echo bar)) 一样轻松嵌套在其自身中。还有其他区别,比如反斜杠在反引号/gravemark版本中是如何解析的等等。

请参阅BashFAQ/082 有几个原因总是更喜欢 $(...) 语法。

有关各种差异的详细信息,另请参阅POSIX 规范。

【讨论】:

不错的链接,但该文本并没有弃用反引号以支持$(...)——它只是将它们作为替代项。 @NormanGray POSIX 可能不会说 deprecated 这个词,但它确实说 "the backquoted variety of command substitution is not recommended" 这只是说不推荐使用恕我直言的冗长方式 POSIX 没有弃用反引号,而是添加了$(...) 作为替代方法。反引号没有已知的实现错误,但$(...) 有许多已知的实现错误。因此,对于可移植性问题,建议对非嵌套调用使用反引号。 $(...) 需要一个递归解析器,但这并没有与引入该功能的 ksh86 一起使用。检查in-ulm.de/~mascheck/various/cmd-subst 以获得正确实现的列表。符合要求的外壳需要支持除案例 D.2 之外的所有案例。 POSIX 中还有其他需要被视为deprecated 的东西,例如使用waitpid() 会阻止您从exit() 参数中看到完整的32 位,但是除了最近的Bourne Shell 之外的所有shell 仍然使用waitpid() 而不是waitid() 调用,该调用现在可用26 年. 答案中的链接暗示了反引号和$()之间存在一些差异,更多解释in this part of the documentation。不同之处不仅在于嵌套。【参考方案3】:

当使用较旧的反引号形式时,反斜杠保留其字面含义,除非后面跟着 $、` 或 \。前面没有反斜杠的第一个反引号终止命令替换。

当使用较新的$(command) 形式时,括号之间的所有字符组成命令;没有人受到特殊对待。

这两种形式都可以嵌套,但反引号品种需要以下形式。

`echo \`foo\`` 

相对于:

$(echo $(foo))

【讨论】:

小幅修正,反引号版本和$() 版本均符合POSIX。【参考方案4】:

它们的行为相同。区别在于语法:嵌套$() 比嵌套`` 更容易:

listing=$(ls -l $(cat filenames.txt))

对比

listing=`ls -l \`cat filenames.txt\``

【讨论】:

echo $(echo \$abc)echo `echo \$abc`‍ 不同 - $(echo \`)$(echo \\) 也存在差异 另一个区别是:echo foo `#comment`echo foo $(#comment)。第二个不行。 (用于在多行命令中进行注释。)【参考方案5】:

2014 年 7 月:commit f25f5e6(Elia Pinto (devzero2000),2014 年 4 月,Git 2.0)增加了嵌套问题:

反引号形式是命令替换的传统方法,并且受 POSIX 支持。但是,除了最简单的用法之外,其他所有用法都会很快变得复杂。 特别是,嵌入式命令替换和/或使用双引号需要 小心使用反斜杠字符转义

这就是git/Documentation/CodingGuidelines 提到的原因:

我们更喜欢$( ... ) 来替换命令; 与 `` 不同,它可以正确嵌套。 Bourne 从第一天起就应该是这样拼写的,但不幸的是不是。

thitoncommented:

这就是为什么`echo `foo`` 不能正常工作的原因,因为每个`` 都可以打开或关闭。 由于运气或特殊功能,它可能适用于特殊情况。


2016 年 1 月更新:Git 2.8(2016 年 3 月)完全摆脱了反引号。

见commit ec1b763,commit 9c10377,commit c7b793a,commit 80a6b3f,commit 9375dcf,commit e74ef60,commit 27fe43e,commit 2525c51,commit becd67f,commit 8c311f9,commit 8c311f9,@987654336 @、commit 1d9e86f、commit 78ba28d、commit efa639f、commit 1be2fa0、commit 38e9476、commit 8823d2f、commit 32858a0、commit cd914d8(2016 年 1 月 12 日)by Elia Pinto (devzero2000)。由Junio C Hamano -- gitster -- 在commit e572fef 中合并,2016 年 1 月 22 日)

从 Git 2.8 开始,都是$(...),不再是`...`

【讨论】:

$() 也是 POSIX 指定的——将反引号描述为“支持 POSIX”的引用暗示这是他们独有的,这是一种误导。只有(1970 年代)pre-POSIX Bourne,反引号是唯一受支持的语法。【参考方案6】:

“这两种方法有什么区别?”

注意这种行为:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

你会得到这些结果:

$A
A_VARIABLE

 

【讨论】:

echo "$(echo "\$A")" 应该与echo "`echo \"\$A\"`" 进行比较。输出是一样的。 我现在尝试了你的符号,输出仍然是 $A 和 A_VARIABLE。 区别在于 $() 不翻译转义 (\$A) 变量和 ` ` 翻译。方法是在 ` ` - \\$A 内加倍转义变量。对此的结论是,您不能简单地将 ` ` 替换为 $( )。需要在里面检查转义字符。 (GNU bash,版本 4.2.46(2)-release (x86_64-redhat-linux-gnu))

以上是关于shell编程中的$(command)和`command`有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

简单shell脚本(mongo)

Linux Shell编程三

编程语言和shell编程的基础内容以及grepegrep命令及相应的正则表达式和用法

shell编程基础

Shell编程基础

编程语言和shell编程的基础内容以及grepegrep命令及相应的正则表达式和用法