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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:50:20  来源:igfitidea点击:

Left side of pipe is the subshell?

bashvariablesunixpipesubshell

提问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 中)执行。