`(反引号/反引号)在命令中是什么意思?

gws*_*gws 222 shell quoting

我遇到了以下命令:

sudo chown `id -u` /somedir
Run Code Online (Sandbox Code Playgroud)

我想知道:`符号的含义是什么。例如,我注意到虽然上面的命令运行良好,但下面的命令却没有:

sudo chown 'id -u' /somedir
Run Code Online (Sandbox Code Playgroud)

roz*_*acz 263

这是一个反引号反引号不是引号。它有一个非常特殊的意义。您在反引号之间键入的所有内容都在主命令之前由 shell 评估(执行)(就像chown在您的示例中一样),并且该执行的输出由该命令使用,就像您在该位置键入该输出一样命令行。

所以呢

sudo chown `id -u` /somedir
Run Code Online (Sandbox Code Playgroud)

有效运行(取决于您的用户 ID)是:

sudo chown 1000 /somedir
  \    \     \     \
   \    \     \     `-- the second argument to "chown" (target directory)
    \    \     `-- your user ID, which is the output of "id -u" command
     \    `-- "chown" command (change ownership of file/directory)
      `-- the "run as root" command; everything after this is run with root privileges
Run Code Online (Sandbox Code Playgroud)

查看这个问题以了解为什么在许多情况下使用反引号不是一个好主意。

顺便说一句,如果您想从字面上使用反引号,例如在字符串中,您可以通过\在它前面放置一个反斜杠 ( )来转义它。

  • 这很好地解释了反引号,但是使用 `$(your expression)` 是一个更好的方法来做同样的事情,因为 `$()` 允许你嵌套表达式。例如:`cd $(dirname $(type -P touch))` 会将你 cd 到包含 `touch` 命令的目录中 (52认同)
  • @KhajaMinhajuddin 您对嵌套绝对正确 - [上述问题](http://unix.stackexchange.com/questions/5778/whats-the-difference-between-stuff-and-stuff) 详细介绍了它。但即使我认为在大多数情况下使用 `$()` 是一个好习惯,它不会使反引号成为*更糟* 的事情。出于实际目的,必须承认它们在命令行上输入要快得多(2 次击键相比至少 5 次,包括“Shift”)。 (12认同)
  • @rozcietrzewiacz 您的后一句话可能适用于大多数键盘,但至少在法语键盘上,`$()` 肯定比 `\` \`` 更容易输入。 (3认同)
  • 图表真的很棒:) (3认同)
  • @KhajaMinhajuddin 你可以嵌套反引号,但你需要逃避第二级反引号,第二级嵌套你需要 3 个反引号,第三级嵌套 5 个反引号,第四级 7,等等。 (2认同)

Kan*_*han 89

我想在这里补充几点。

反引号`…`实际上称为命令替换。命令替换的目的是评估放置在反引号内的命令,并将其结果作为实际命令的参数提供。

命令替换可以通过两种方式完成,一种是使用$(…),另一种是`…`. 两者的工作方式相同,但$(…)形式是现代方式,具有更高的清晰度和可读性。

所以

sudo chown $(id -u) /somedir
Run Code Online (Sandbox Code Playgroud)

可以优先于另一个。

这里还需要注意的一件事是命令替换与bash文档中提到的bash 引用规则的关系。

如果替换出现在双引号内,则不会对结果执行分词和文件名扩展。

  • 此外,`$(...)` 嵌套更好。 (10认同)
  • `$()` 和 `"``"` 的工作方式不同 (2认同)

小智 12

一项说明很少涉及:

反引号(有时也称为 Graves,因为它兼作法语和其他语言中的常见口音)替代标准输出,而不替代标准错误。

所以继续前面的例子:

file `which hostname`
Run Code Online (Sandbox Code Playgroud)

将按预期工作,但在:

file `which hostnameX`
Run Code Online (Sandbox Code Playgroud)

which将返回一个错误,并且该输出进入标准错误,而不是替换到旁边的命令行file;根本没有标准输出,您可以通过运行来确认:

which hostnameX

which hostnameX 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

在这种情况下,

file `which hostnameX` 
Run Code Online (Sandbox Code Playgroud)

将产生两个错误消息(第一个,由于which hostnameX和第二个紧随前者,由于文件本身,发现文件名丢失,因此,整个命令

基本上会减少到:

file
Run Code Online (Sandbox Code Playgroud)

这当然是不好的用法,并且会返回一个 Usage 错误。

(如果你想自己检查,你可以尝试:

file `which hostnameX 2>/dev/null`    # just the file-command bad-usage error msg is printed

file `which hostnameX 2>/dev/null` 2>/dev/null  # now nothing is printed on the screen :)
Run Code Online (Sandbox Code Playgroud)


Jul*_*ian 5

反引号 ` 运行封闭字符串的内容,所以像这样

file `which hostname`
Run Code Online (Sandbox Code Playgroud)

将找出主机名命令的路径,然后告诉您它是如何构建的。

您在问题中输入的命令会运行id -u以获取有效的用户 ID,然后将 /somedir 的所有权更改为该用户。