在shell编程中,$(command)和`command`有什么区别?

kcrjzv8t  于 2023-10-23  发布在  Shell
关注(0)|答案(7)|浏览(119)

要将命令的输出作为变量存储在sh/ksh/bash中,可以执行以下操作之一

var=$(command)

var=`command`

如果这两种方法有什么区别的话,那有什么区别呢?

j0pj023g

j0pj023g1#

反引号/gravemark已经被弃用,而支持$()作为命令替换,因为$()可以像$(echo foo$(echo bar))一样轻松地嵌套在自己内部。还有其他的区别,比如反斜线在反勾号/gravemark版本中是如何解析的,等等。
请参阅BashFAQ/082,了解始终首选$(...)语法的几个原因。
有关各种差异的详细信息,请参阅POSIX规范。

5sxhfpxr

5sxhfpxr2#

他们的行为是一样的。区别在于语法:嵌套$()比嵌套````更容易:

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

vs.

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

6qftjkof3#

2014年7月:commit f25f5e6(by Elia Pinto ( devzero2000 ),April 2014,Git 2.0)增加了嵌套问题:
反引号形式是命令替换的传统方法,并且由POSIX支持。

**然而,除了最简单的用法外,所有的用法都很快变得复杂。

特别是,嵌入式命令替换和/或双引号的使用需要小心地使用反斜杠字符**进行转义。
这就是为什么git/Documentation/CodingGuidelines提到:
我们更喜欢$( ... )作为命令替换;**不像,它正确地嵌套**。 伯恩从第一天起就应该这样拼写,但不幸的是不是。 [thiton](https://stackoverflow.com/users/847601/thiton)评论: 这就是为什么echo foo```一般不工作的原因,因为每个````都可以打开或关闭,因此存在固有的模糊性。 它可能会因运气或特殊功能而适用于特殊情况。 2016年1月更新:Git 2.8(2016年3月)完全去除了反引号。 参见[commit ec1b763](https://github.com/git/git/commit/ec1b763d05bb03d8741c1363d7acf4ccb7153f6d)、[commit 9c10377](https://github.com/git/git/commit/9c1037751c0204c494b1ed49e8c1d94429ea78b1)、[commit c7b793a](https://github.com/git/git/commit/c7b793a17d92350632c51a24e06b6a3dc4a93c2b)、[commit 80a6b3f](https://github.com/git/git/commit/80a6b3f0d54d0df6c6994df5486433bf0b9a54c0)、[commit 9375dcf](https://github.com/git/git/commit/9375dcf3b9bb1e462e28d5017165e1c7fa741c77)、[commit e74ef60](https://github.com/git/git/commit/e74ef604974192712c38f77cd751b00ad36e1378)、[commit 27fe43e](https://github.com/git/git/commit/27fe43e869f4ee8865beeedf6f2bbbab07cf0c7c)、[commit 2525c51](https://github.com/git/git/commit/2525c5170f1088dac0aeb18444041f9fff04761a)、[commit becd67f](https://github.com/git/git/commit/becd67fd281fa0efdf8f6346f311954a237dc991)、[commit a5c98ac](https://github.com/git/git/commit/a5c98acec6ad8e8c397b1001621a4edfacc98516)、[commit 8c311f9](https://github.com/git/git/commit/8c311f96a5a089d2f35654e9af7c44377a27839b)、[commit 57da049](https://github.com/git/git/commit/57da04965d56c7d7da6a00c3fb6fc3981cf0ba9a)、[commit 1d9e86f](https://github.com/git/git/commit/1d9e86f80d2ede6829c57ef4b22e4dd8b162cc7e)、[commit 78ba28d](https://github.com/git/git/commit/78ba28d84b5be8cbb1d5d5e7d65b5522739ad5ce)、[commit efa639f](https://github.com/git/git/commit/efa639fe6b850de699b675bf3e9c4b35f54f54bc)、[commit 1be2fa0](https://github.com/git/git/commit/1be2fa02b5ac97346e6745c767c559ee363ff378)、[commit 38e9476](https://github.com/git/git/commit/38e947660b2bb09e035f91b682b7011c2808052e),[commit 8823d2f](https://github.com/git/git/commit/8823d2fa792efbc89d3ab1392a4b064e8fbd6705),[commit 32858a0](https://github.com/git/git/commit/32858a01506b22963cfd5f8c8db95486f26133af),[commit cd914d8](https://github.com/git/git/commit/cd914d8090d64c8df1b0c45327de7dacdf370a09)(12 Jan 2016)by [Elia Pinto (devzero2000)](https://github.com/devzero2000) . (由[Junio C Hamano --gitster--](https://github.com/gitster)合并至[commit e572fef](https://github.com/git/git/commit/e572fef9d459497de2bd719747d5625a27c9b41d),2016年1月22日) 从Git 2.8开始,它都是$(...)`,不再是...

uxhixvfz

uxhixvfz4#

当使用旧的反勾形式时,反斜杠保留其字面意义,除非后跟$,或\。第一个不带反斜杠的反勾号终止命令替换。 当使用较新的$(command)`时,括号之间的所有字符组成命令;没有一个是特殊处理的。
这两种形式都可以嵌套,但反勾号类型需要以下形式。

`echo \`foo\``

相反:

$(echo $(foo))
oxf4rvwz

oxf4rvwz5#

除了可以在命令中使用的非转义字符之外,几乎没有什么区别。您甚至可以将**...命令放在$(...)命令中(反之亦然),以实现更复杂的两级命令替换。
对反斜杠字符/操作符的解释略有不同。除此之外,当嵌套
...替换命令时,必须用\,转义内部的`字符,而用$()**替换它会自动理解嵌套。

eit6fx6z

eit6fx6z6#

“这两种方法有什么区别?”
注意这种行为:

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

你会得到这些结果:

$A
A_VARIABLE
zd287kbt

zd287kbt7#

反引号和用于命令替换的较新的首选POSIX语法之间的一个新的区别是如何处理注解。反引号中的哈希字符创建了一个以第二个反引号字符结束的注解,有效地创建了一种具有中间行注解的方法。

$ 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 ")")

相关问题