$()是subshel​​l吗?


Answers:


75

$(…)从定义上讲,它是一个子Shell:它是Shell运行时状态¹的副本,并且对该子Shell中状态的更改对父级没有影响。子外壳程序通常是通过派生新进程来实现的(但某些外壳程序在某些情况下可能会对此进行优化)。

它不是您可以从中检索变量值的子外壳。如果对变量的更改对父级有影响,那么它将不是子shell。这是一个子shell,其父级可以检索其输出。由创建的子外壳将$(…)其标准输出设置为管道,并且父级从该管道读取并收集输出。

还有其他几种创建子外壳的构造。我认为这是bash的完整列表:

  • 用于分组( … )的子shell :除了创建子shell并等待其终止之外,什么都不做。与{ … }纯粹出于语法目的而命令的组相反,而不创建子shell。
  • 背景… &创建一个子外壳,不等待它终止。
  • Pipeline… | …创建两个子外壳,一个用于左侧,一个用于右侧,然后等待两者终止。外壳程序创建一个管道,并将左侧的标准输出连接到管道的写入端,并将右侧的标准输入连接到读取端。在某些shell(ksh88,ksh93,zsh,bash中具有设置的lastpipe选项和有效选项)中,右侧在原始shell中运行,因此管道构造仅创建一个子shell。
  • 命令替换:($(…)也拼写为`…`)创建一个子shell,其标准输出设置为管道,收集父级中的输出,并扩展到该输出,减去尾随的换行符。(并且输出可能会进一步分裂和阻塞,但这是另一回事了。)
  • 流程替换<(…)创建一个子shell,并将其标准输出设置为管道,然后扩展为管道的名称。父级(或其他进程)可以打开管道以与子外壳进行通信。>(…)相同,但管道在标准输入上。
  • Coprocesscoproc …创建一个子外壳,不等待其终止。子外壳的标准输入和输出每个都设置为一个管道,其父级连接到每个管道的另一端。

¹ 与运行单独的shell相对


您还可以${...}在答案中包含吗?
user1717828'5

3
@ user1717828什么?为什么?变量扩展远程与此问题有什么关系?我不会在回答中包含整个shell手册。
吉尔斯(Gilles)'所以

1
变量扩展远程与此问题有什么关系? 我不知道,这就是为什么我问:-)因此,我猜花括号替换与括号替换完全不同。
user1717828'5

@ user1717828:变量扩展与子外壳无关;这是完全独立的机制,如果您刚开始,绝对值得一读!
0xdd

1
@EnricoMariaDeAngelis这不是唯一的方法,而是最自然的方法。另一种方法是command | { read line; … }(取决于外壳,line流水线之后可能还是可能不可用)。所有方式都涉及一个子外壳,因为产生输出的命令必须独立于读取输入的外壳运行。如果命令是纯内部的(只有shell构造和内置命令,没有外部命令),则该shell可能不会创建子进程,但这只是一个优化,它仍会创建一个子shell。
吉尔斯(Gilles)“所以

20

从bash版本4.4中的bash(1)手册页的“ EXPANSION”部分,“ Command Substitution”子部分中:

Bash通过command在子shell环境中执行来执行扩展[...]



1
有趣的是,在CentOS 7下,该手册bash页没有提到任何子外壳:Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.我想知道这是否是故意的遗漏。
dr01

6
@ dr01相反,bash 4.4将该句子的措词更改为包含“ subshel​​l”一词。这是一种澄清:手册明确提到了各种其他构造都是子外壳,但是直到4.4才明确指出它不是用于命令替换的。
吉尔斯(Gilles)'所以

是的,在CentOS v7.4.1708(相当近期)上,bash是v4.2.46。
dr01

5

是的,( commands... )bashcommands...在另一个进程中执行的子shell 。

唯一的区别$( commands... )是,这部分代码将在执行后commands...替换为commands...写入的所有内容stdout

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.