在花括号和管道中分组命令不会保留变量

时间:2015-06-09 09:05:25

标签: bash

说我当前的工作目录中有一个文件myfile。如果命令正常执行,我想设置一个变量,但也要使用它的结果。

$ ls myfile && v=3
myfile
$ echo "$v"
3

但是现在我也想管道结果,所以我使用{ list; }语法对命令进行分组:

$ unset v
$ { ls myfile && v=3; } | grep myf
myfile
$ echo "$v"
                  # v is not set

Bash reference manual -> 3.2.4.3 Grouping Commands说:

{ list; }
     

在花括号之间放置一个命令列表会导致列表成为   在当前shell上下文中执行。没有创建子shell。该   需要以下分号的分号(或换行符)。

所以,根据我的理解,v应该设置为3.但它没有发生。为什么呢?

2 个答案:

答案 0 :(得分:6)

这不是导致子壳创建的花括号,而是管道。

证明:

$ { ls && v=3; } > tmp
$ echo "$v"
3

引用Greg

  

在大多数shell中,管道的每个命令都在一个单独的SubShell中执行。

答案 1 :(得分:4)

您可以使用BASH_SUBSHELL变量来验证您是否在子shell中。

# BASH_SUBSHELL will print level of subshell from top due to pipe
{ unset v && ls file && v=3 && echo "$BASH_SUBSHELL - $v"; } | nl
     1  file
     2  1 - 3

# outside BASH_SUBSHELL will print 0
echo "$BASH_SUBSHELL - $v";
0 -

您可以使用管道命令打印1,这意味着它位于子shell中,因此v的值在外部不可用(从第二个输出显而易见)