子管的左侧是子壳?

nhe*_*hed 11 unix variables bash pipe subshell

编辑:

我在下面的评论 sed 's@^@ @' <(f1)是不正确的虽然$BASH_SUBSHELL表明我们与启动处于同一级别,但变量在主脚本中丢失.根据戈登的回答,我测试了f1 > >(sed 's@^@ @'),这似乎工作正常.不过,对于第一种形式,BASH_SUBSHELL不应该是1而不是0吗?


考虑这个小测试

#!/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"
Run Code Online (Sandbox Code Playgroud)

具有以下输出:

In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1
Run Code Online (Sandbox Code Playgroud)

(目的sed只是为了得到一些东西,不要指望它做任何事情,因为f1输出到stderr)

函数f1记录当前的BASH_SUBSHELL和i的当前值

我知道为什么在我们得到的脚本结束时i=1,因为第二次调用是在子shell中,并且子shell 1中i的值丢失了.

我不知道为什么管道的左侧没有在当前的shell中执行

虽然我认为我可以避免这种情况,但sed 's@^@ @' <(f1) 我想知道为什么左侧与主脚本不在同一级别

Gor*_*son 18

bash手册页:"管道中的每个命令都作为一个单独的进程执行(即,在子shell中)." 我想可以在当前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"
Run Code Online (Sandbox Code Playgroud)

它打印:

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
Run Code Online (Sandbox Code Playgroud)

因为管道中f1的所有3次调用都在子壳中运行.

  • @nhed :(继续)例如,要强制管道中的第一个命令在主shell中运行,请使用`cmd1 >>(cmd2 | cmd3 | ...)`.要在主shell中运行cmd2,请使用`cmd2 <<(cmd1)>>(cmd3 | ...)`等. (5认同)
  • bash确实发挥了收藏夹的作用,因此产生了一些小问题:[管道左侧的`jobs`不在子外壳中运行“(http://unix.stackexchange.com/a/279792/50240)。 (3认同)