版本4.4.19的bash
手册页说:
管道
管道是由一个控制操作符
|
或|&
分隔的一个或多个命令的序列。管道的格式是:
[time [-p]] [ ! ] command [ [|||&] command2 ... ]
不确定。那讲得通。然后,在该部分的后面:
管道中的每个命令都作为一个单独的进程执行(即在子shell中)。
同样合理,也很容易证明:
$ pwd
/Users/ravron
$ ls | grep src # yes, src _does_ exist
src
$ cd src | true # cd in subshell has no effect on parent session
$ pwd
/Users/ravron
但是,我注意到上面的管道定义的措辞使得即使是简单的命令也是管道。毕竟,在语法中,除command
之外的所有内容都是可选的:
[time [-p]] [ ! ] command [ [|||&] command2 ... ]
现在,当然,运行甚至单个命令 - 在man bash
术语中,“简单命令” - 在子壳中实际上是非常无用的。 cd
不起作用,变量设置不起作用等等。然而,现实 - 简单的命令,尽管匹配(相当简并)管道的语法,不在子壳中执行 - 似乎在手册的几率。在列表表格中,这是我的理解:
我错过了什么,或者这是man bash
中无可否认的无关紧要的错误?
答案 0 :(得分:3)
手册简直不精确。 POSIX规范(第2.12节)更明确(我添加了粗体):
默认情况下,此外,多命令管道的每个命令都在一个 子shell 环境;但是,作为扩展,中的任何或所有命令 管道可以在当前环境中执行。所有其他 命令应在当前的shell环境中执行。
bash
将每个子shell的实现位置作为子进程。 (lastpipe
4.2中引入的bash
选项允许最终命令在当前shell环境/进程中执行。)
shell的语法说管道可以包含一个或多个命令,但是shell的语义区分了一个命令的管道和两个或多个命令的管道。
答案 1 :(得分:1)
手册永远不会定义单词" subshell"。虽然您可能直观地假设子shell始终是原始shell的子进程,但是单个命令的退化情况使用原始shell进程作为子shell。
其他一些shell更进一步,总是在原始shell的管道中运行最后一个命令。