在sh/ksh/bash中将命令的输出存储为变量,可以使用以下任一方法:
var=$(command)
或者var=`command`
这两种方法有什么区别(如果有的话)?
为了替代反引号/重音符,现已废弃使用$()来进行命令替换,因为$()可以轻松地嵌套在自身中,例如$(echo foo$(echo bar))。 在反引号/重音符版本中,反斜杠的解析方式等方面存在其他差异。
请参阅BashFAQ/082,以获取始终首选$(...)语法的多个原因。
另请参阅POSIX规范,以获取有关各种差异的详细信息。
$(...)
替代反引号,只是把它们作为另一种选择提供了说明。 - Norman Gray$(...)
作为替代方法。没有已知的反引号实现错误,但有许多已知的$(...)
实现错误。因此,为了可移植性问题,建议在非嵌套调用中使用反引号。$(...)
需要递归解析器,但这在引入该功能的ksh86中未使用。请查看http://www.in-ulm.de/~mascheck/various/cmd-subst/以获取正确实现的列表。符合规范的shell需要支持除D.2案例外的所有情况。 - schilywaitpid()
会阻止您看到来自exit()
参数的完整32位,但除最近的Bourne Shell外,所有shell仍然使用waitpid()
而不是现在已经可用26年的waitid()
调用。 - schily它们的行为相同。不同之处在于语法:嵌套 $()
比 ``
更容易:
listing=$(ls -l $(cat filenames.txt))
对比。
listing=`ls -l \`cat filenames.txt\``
echo $(echo \$abc)
和 echo `echo \$abc`
是不同的 - 对于 $(echo \`)
和 $(echo \\)
也存在差异。 - Peter.Oecho foo \
#comment`与
echo foo $(#comment)`。第二个不起作用。(用于在多行命令中进行注释。) - wisbucky2014年7月:Elia Pinto (devzero2000
)在Git 2.0中提交的commit f25f5e6解决了嵌套问题:
反引号形式是命令替换的传统方法,符合POSIX标准。
然而,除了最简单的用法之外,其他用法很快就变得复杂起来。
特别是嵌套命令替换和/或双引号的使用需要小心使用反斜杠字符进行转义。
这就是为什么git/Documentation/CodingGuidelines提到:
我们更喜欢使用$( ... )
进行命令替换;与 `` 不同,它可以正确嵌套。从一开始就应该是 Bourne 的拼写方式,但不幸的是它并不是。`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 a5c98ac, commit 8c311f9, commit 57da049, commit 1d9e86f, commit 78ba28d, commit efa639f, commit 1be2fa0, commit 38e9476, commit 8823d2f, commit 32858a0, commit cd914d8 (2016年1月12日) 由Elia Pinto (devzero2000
)提交。
(由Junio C Hamano -- gitster
--合并于commit e572fef,2016年1月22日)
$(...)
,不再使用`...`
。$()
也是符合POSIX标准的 -- 描述反引号为“POSIX支持”的引用,会让人错误地认为这是它们所独有的,这是具有误导性的。只有在上世纪70年代之前的Bourne shell中,反引号才是唯一支持的语法。 - Charles Duffy使用旧的反引号形式时,反斜杠保留其文字意义,除非其后面跟着 $、` 或 \。第一个未经反斜杠转义的反引号终止命令替换。
使用新的 $(command)
形式时,括号内的所有字符都构成命令;没有特殊处理。
这两种形式都可以嵌套,但是反引号形式需要使用以下形式。
`echo \`foo\``
相对于:
$(echo $(foo))
$()
版本都符合POSIX标准。 - SiegeX除了可以在命令中使用未转义的字符之外,几乎没有什么区别。您甚至可以将`...`命令放在$(...)命令内部(反之亦然),以进行更复杂的两级深度命令替换。
反斜杠字符/运算符的解释略有不同。当嵌套`...`替换命令时,您必须使用\,转义内部的`字符,而对于$()替换,则会自动理解嵌套。
A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"
您将获得以下结果:
$A
A_VARIABLE
echo "$(echo "\$A")"
应该与 echo "\
echo "$A"`"` 进行比较。输出结果相同。 - FooF
会翻译。解决方法是在
中双重转义变量 - \\$A
。
因此,结论是不能简单地用 $( ) 替换
。需要检查其中的转义字符。
(GNU bash,版本4.2.46(2)-release(x86_64-redhat-linux-gnu)) - Hiro$ echo "Goodbye` # Cruel` World"
Goodbye World
$ echo "Goodbye$( # Cruel
> ) World"
Goodbye World
$ echo "Goodbye$( # Cruel) World"
>
sh -c
来强制将其限制在一行。然后你会发现这会导致语法错误。$ sh -c 'echo "Goodbye$( # Cruel) World"'
sh: 1: Syntax error: end of file unexpected (expecting ")")