Bash 大括号和管道中的分组命令不会保留变量
假设我在当前工作目录中有一个文件Bash 大括号和管道中的分组命令不会保留变量,bash,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 将命令列表放置在大括号之间会导
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
将命令列表放置在大括号之间会导致该列表
在当前shell上下文中执行。没有创建子shell。这个
以下列表需要分号(或换行符)
因此,根据我的理解,
v
应该设置为3。但事实并非如此。为什么?创建子shell的不是花括号,而是管道
为了证明这一点:
$ { ls && v=3; } > tmp
$ echo "$v"
3
引述:
在大多数shell中,管道的每个命令都在单独的子shell中执行
您可以使用变量来验证是否在子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
的值在外部不可用(从第二次输出中可以明显看出)ooh,因此v=1 | echo“hi”
将是相同的情况。是的,对v
的更改将仅在子shell的生存期内持续。正确,因为v=2;v=1 | echo“hi,v=$v”
返回“hi,v=2”。很有趣,非常感谢@看我的答案。这几乎是一样的。感谢你的技巧,anubhava,你总是会带来一些有趣的东西:)$BASHPID还可以用来获取shell实例的真实PID。
# 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 -