dre*_*cko 3 bash scope loops pipe
我注意到,如果我管道循环的输出,bash for循环中的变量范围似乎会改变.
例如,g循环后此处仍保持更改:
$ g=bing; for f in foo; do g=fing; echo g in loop: $g; done; echo g after $g;
g in loop: fing
g after fing
Run Code Online (Sandbox Code Playgroud)
而在这里,循环中的变化被遗忘:
$ g=bing; for f in foo; do g=fing; echo g in loop: $g; done | cat; echo g after $g;
g in loop: fing
g after bing
Run Code Online (Sandbox Code Playgroud)
g管道接收器中的值也来自"外部"上下文:
$ g=bing; for f in foo; do g=fing; echo g in loop: $g; done | (cat; echo in pipe $g;); echo g after $g;
g in loop: fing
in pipe bing
g after bing
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?
来自bash手册页
管道中的每个命令都作为单独的进程执行(即,在子shell中).
这意味着管道的两侧都在子shell中运行.
来自http://www.tldp.org/LDP/abs/html/subshells.html
子shell中的变量在子shell中的代码块之外是不可见的.父进程无法访问它们,无法访问启动子shell的shell.实际上,这些是子进程本地的变量.
这意味着当管道结束时,对变量的所有更改都将丢失.
以下是该理论使用的概念证明 BASH_SUBSHELL
BASH_SUBSHELL每次生成子shell或子shell环境时增加1.初始值为0.
输入:
echo "before loop:$BASH_SUBSHELL"
for i in foo; do echo "in loop:$BASH_SUBSHELL"; done | (cat;echo "second pipe: $BASH_SUBSHELL")
echo "out of pipe: $BASH_SUBSHELL"
Run Code Online (Sandbox Code Playgroud)
输出:
before loop:0
in loop:1
second pipe: 1
out of pipe: 0
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,循环内部和管道的第二部分都已在子壳内运行,并且它们终止于管道的末端.
编辑2
意识到这样做可能更清楚,以显示运行的不同子壳
在旧的bashes中,它不包含$ BASHPID,这实际上是查看子shell的pid的唯一方法,但是你可以声明一个像
GetPid(){ cut -d " " -f 4 /proc/self/stat; }
Run Code Online (Sandbox Code Playgroud)
它的工作原理基本相同
echo -n "before loop:";GetPid
for i in foo; do echo -n "in loop:";GetPid; done | (cat;echo -n "second pipe:";GetPid)
echo -n "out of pipe:";GetPid
Run Code Online (Sandbox Code Playgroud)
echo "before loop:$BASHPID"
for i in foo; do echo "in loop:$BASHPID"; done | (cat;echo "second pipe: $BASHPID")
echo "out of pipe: $BASHPID"
Run Code Online (Sandbox Code Playgroud)
输出:
before loop:29985
in loop:12170
second pipe:12171
out of pipe:29985
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这使得在管道之前和之后您与原始变量位于同一个shell中更加清晰.
你的第三种情况也得到了解决,因为管道的两侧都在不同的子壳中运行,变量被重置为每个管道命令的父值,所以即使它仍然是相同的管道,它也会在循环之后恢复.
| 归档时间: |
|
| 查看次数: |
309 次 |
| 最近记录: |