bash 管道的左侧是子壳?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5760640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Left side of pipe is the subshell?
提问by nhed
Edit:
编辑:
My comment below regarding sed 's@^@ @' <(f1)is incorrect
While $BASH_SUBSHELLindicates that we are in the same level as the launch, the variables are lost in the main script.
based on Gordons answer I tested f1 > >(sed 's@^@ @')instead and that seems to work correctly. Still, shouldn't BASH_SUBSHELL should be 1 and not 0 for the first form?
我在下面的评论 sed 's@^@ @' <(f1)是不正确的,虽然$BASH_SUBSHELL表明我们与发布处于同一级别,但主脚本中的变量丢失了。基于 Gordons 的回答,我进行了测试f1 > >(sed 's@^@ @'),这似乎可以正常工作。不过,对于第一种形式, BASH_SUBSHELL 不应该是 1 而不是 0 吗?
Consider this small test
考虑这个小测试
#!/bin/bash
declare -i i=0
function f1()
{
let i++
echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}
f1
f1 | sed 's@^@ @'
echo "at end, i=$i"
with the following output:
具有以下输出:
In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1
(the purpose of the sedis just to have a pipe to something, don't expect it to do anything because f1 outputs to stderr)
(的目的sed只是为了有一个管道,不要指望它做任何事情,因为 f1 输出到 stderr)
The function f1 logs the current BASH_SUBSHELL and the current value of i
函数 f1 记录当前的 BASH_SUBSHELL 和 i 的当前值
I know why at the end of the script we get i=1, its because the second invocation was in a subshell, and the value of i at subshell 1 was lost.
我知道为什么在脚本末尾我们得到i=1,这是因为第二次调用是在子外壳中,而子外壳 1 处的 i 值丢失了。
What I don't know is why the left side of the pipe was not executed in the current shell
我不知道的是为什么在当前shell中没有执行管道的左侧
Though I figured that I could avoid this with sed 's@^@ @' <(f1)I would like to know why the left side is not at the same level as the main script
虽然我认为我可以避免这种情况,但sed 's@^@ @' <(f1)我想知道为什么左侧与主脚本不在同一级别
回答by Gordon Davisson
From the bash man page: "Each command in a pipeline is executed as a separate process (i.e., in a subshell)." I suppose it would be possible to execute one component of a pipeline in the current shell (i.e. the first, or the last, or maybe one in the middle), it doesn't play favorites like this: they allexecute in subshells. If you modify your script like this:
来自bash 手册页:“管道中的每个命令都作为单独的进程(即,在子外壳中)执行。” 我想可以在当前 shell 中执行管道的一个组件(即第一个,或最后一个,或者可能是中间的一个),它不会像这样播放收藏夹:它们都在子 shell 中执行。如果您像这样修改脚本:
#!/bin/bash
declare -i i=0
function f1()
{
let i++
echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}
f1
f1 | f1 | f1
echo "at end, i=$i"
it prints:
它打印:
In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
at end, i=1
because all 3 invocations of f1 in the pipeline run in subshells.
因为管道中对 f1 的所有 3 次调用都在子 shell 中运行。
回答by RzR
Here is a much concise example if someone cares :
如果有人关心,这是一个非常简洁的例子:
cd / && cd /tmp/ | pwd ; pwd
/
/
Or :
或者 :
cd / && cd /tmp/ | cd /var/ ; pwd
/
Yes this page says it all
是的,这个页面说明了一切
http://linux.die.net/man/1/bash#Each command in a pipeline is executed as a separate process (i.e., in a subshell).
http://linux.die.net/man/1/bash#管道中的每个命令都作为单独的进程(即,在子shell 中)执行。

