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`有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章