昨天有人建议我在 bash 中使用命令替换会导致产生不必要的子 shell。该建议针对此用例:
# Extra subshell spawned
foo=$(command; echo $?)
# No extra subshell
command
foo=$?
尽我所能,这对于这个用例来说似乎是正确的。然而,试图验证这一点的快速搜索会导致大量令人困惑和矛盾的建议。似乎流行的智慧说所有命令替换的使用都会产生一个子shell。例如:
命令替换扩展到命令的输出。这些命令在 subshell 中执行,它们的标准输出数据是替换语法扩展的内容。(来源)
这似乎很简单,除非您继续挖掘,在这种情况下,您将开始找到对事实并非如此的建议的引用。
命令替换不一定会调用 subshell,并且在大多数情况下不会。它唯一保证的是无序评估:它只是先评估替换中的表达式,然后使用替换的结果评估周围的语句。(来源)
这似乎很合理,但这是真的吗?This answer to a subshell related question提示我man bash
注意以下事项:
管道中的每个命令都作为单独的进程执行(即,在子shell 中)。
这让我想到了主要问题。究竟什么会导致命令替换产生一个无论如何都不会产生的子shell来单独执行相同的命令?
请考虑以下情况并解释哪些情况会产生额外子外壳的开销:
# Case #1
command1
var=$(command1)
# Case #2
command1 | command2
var=$(command1 | command2)
# Case #3
command1 | command 2 ; var=$?
var=$(command1 | command2 ; echo $?)
这些对中的每一对都会产生相同数量的子shell来执行吗?POSIX 与 bash 实现有区别吗?在其他情况下,使用命令替换会产生一个子shell,而单独运行同一组命令则不会?