庆典:从循环管路的输出似乎改变内环路范围 - 为什么? [英] bash: piping output from a loop seems to change the scope within the loop - why?

查看:110
本文介绍了庆典:从循环管路的输出似乎改变内环路范围 - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,循环是bash中的变量范围似乎改变,如果我管回路的输出。

I've noticed that variable scope within a bash for loop seems to change if I pipe the output of the loop.

例如,这里先按g 在循环后仍改:

For example, here g remains changed after the loop:

$ 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

而在这里,在循环过程中的变化被遗忘的:

whereas here, the change during the loop is forgotten:

$ 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

先按g 在管道的接收器的值是从外部环境太:

The value of g in the receiver of the pipe is from the "outer" context too:

$ 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

这是怎么回事?

推荐答案

从bash的手册页

在管道中的每个命令都作为单独的进程中执行(即,在一个子shell)。

Each command in a pipeline is executed as a separate process (i.e., in a subshell).

这意味着,管道的两侧子外壳中运行。

This means that both sides of the pipeline are run in a subshell.

http://www.tldp.org/LDP/abs/html /subshel​​ls.html

在子shell变量不是code在壳层块外部可见。他们不是父进程访问,到推出了子shell的外壳。这些实际上,局部变量的子进程。

Variables in a subshell are not visible outside the block of code in the subshell. They are not accessible to the parent process, to the shell that launched the subshell. These are, in effect, variables local to the child process.

这意味着,当管道结束所有变更变量都将丢失。

This means that when the pipeline ends all changes to variables are lost.

下面是概念的这个理论使用证明 BASH_SUBSHELL

Here is a proof of concept for this theory using BASH_SUBSHELL

BASH_SUBSHELL
  一个每一个子shell子shell或环境的催生时间递增。的初始值是0。

BASH_SUBSHELL Incremented by one each time a subshell or subshell environment is spawned. The initial value is 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"

输出:

before loop:0
in loop:1
second pipe: 1
out of pipe: 0

正如你可以看到两个环和管的第二部分内已被内子shell运行,并且它们最终在管道的端部。

As you can see both inside the loop and the second part of the pipe have been run inside subshells, and they end at the end of the pipeline.

编辑2

已实现它可能是更清楚这样做是为了证明那些运行不同的子shell

Realised it was probably clearer to do this to show the different subshells that are run

在旧打击并可以击晕它不包括$ BASHPID这实在是看子shell的pid的唯一途径,但你可以像声明

In old bashes it doesn't include $BASHPID which is really the only way to see the pid of subshells, but you can declare a function like

GetPid(){ cut -d " " -f 4 /proc/self/stat; }

其中工程pretty大同小异

which works pretty much the same



Bash 4.0+

猛砸4.0 +

Output:

输出:

As you can see this makes it clearer that before and after the pipeline you are in the same shell with the original variable.
Your third case is also solved as both sides of the pipe run in different subshells the variable is reset to the parent value for each piped command, so will have reverted back after the loop, even though it is still the same pipeline.

这篇关于庆典:从循环管路的输出似乎改变内环路范围 - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆