子管的左侧是子壳?

时间:2011-04-22 22:22:53

标签: bash variables unix pipe subshell

编辑:

我在下面关于sed 's@^@ @' <(f1)的评论不正确 虽然$BASH_SUBSHELL表示我们与启动处于同一级别,但变量在主脚本中丢失。 根据Gordons的回答,我测试了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"

使用以下输出:

In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1

sed的目的只是为了管道,不要指望它做什么,因为f1输出到stderr)

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

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

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

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

2 个答案:

答案 0 :(得分:17)

bash man page:“管道中的每个命令都作为一个单独的进程执行(即在子shell中)。”我想可以在当前shell中执行管道的一个组件(即第一个,或者最后一个,或者可能是中间的一个),它不会像这样播放收藏夹:它们 all 在子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"

打印:

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

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

答案 1 :(得分:-1)

如果有人关心,这是一个非常简洁的例子:

cd / && cd /tmp/ | pwd  ; pwd
/
/

或者:

cd / && cd /tmp/ | cd /var/  ; pwd
/

是的,这一页说明了一切

http://linux.die.net/man/1/bash#管道中的每个命令都作为一个单独的进程执行(即在子shell中)。