From: Lew Pitcher on 16 Jul 2010 18:11 On July 16, 2010 17:43, in comp.unix.shell, ceaus(a)nospam wrote: > Hi, > > What gives? Is this a bash bug? Nope. It's a sign that you don't understand how pipes work in bash. > Note the different output for 'while' and 'for' > > ------------------------------------------------------------ > function foo() { > echo Foo | while read x > do > var=2 > done > } > var=1 > echo $var # prints 1 > foo > echo $var # prints 1 the right-hand-side of the pipe runs in a subshell. This means that the while read x do var=2 done portion of the code has no write access to the environment variables on the echo Foo side of the pipe. Your commandline shell resides on the echo Foo side of the pipe. What happens is this: In your main shell, you set var=1 You then run function foo, which, in your main shell performs an echo Foo piping the stdout from echo into the stdin of a 2nd process. The main shell then waited for that 2nd process to finish. Now, the 2nd process inherited your var=1 and changed *it's inherited value* to 2. This second process then terminated, and it's environment was discarded. Including the changed value of var, which (as a changed value) only existed in this second process. When the 2nd process finished, your commandline shell reaped it's status, and gave you another prompt. you then echo $var and find that, in this first process, var had not changed. That's because it had changed *only in the 2nd process*, and was discarded. > ------------------------------------------------------------ > function foo() { > for x in Foo > do > var=2 > done > } > var=1 > echo $var # prints 1 > foo > echo $var # prints 2 Here, because no pipe is involved, no second process is started. The entire command is executed within the process that is your commandline shell. This means that the script given above has write access to environment variables in the commandline shell, and you see that the script has changed one of the environment variable values. > ------------------------------------------------------------ > > > bash = GNU bash, versie 4.0.35(1)-release (x86_64-suse-linux-gnu) > > Ceaus HTH -- Lew Pitcher Master Codewright & JOAT-in-training | Registered Linux User #112576 Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/ ---------- Slackware - Because I know what I'm doing. ------
From: Jon LaBadie on 16 Jul 2010 18:13 Ceaus wrote: > Hi, > > What gives? Is this a bash bug? > Note the different output for 'while' and 'for' > > ------------------------------------------------------------ > function foo() { > echo Foo | while read x > do > var=2 > done > } > var=1 > echo $var # prints 1 > foo > echo $var # prints 1 > ------------------------------------------------------------ > function foo() { > for x in Foo > do > var=2 > done > } > var=1 > echo $var # prints 1 > foo > echo $var # prints 2 > ------------------------------------------------------------ > Not a bug. When a control structure is redirected, bash runs the code in a child process. Therefore, in the parent, the variable is unchanged. Change your second function to: echo Foo | for x in Foo And it too will print out 1&1. jl
From: Sven Mascheck on 16 Jul 2010 18:54 Jon LaBadie wrote: >> [...] >> echo Foo | while read x > When a control structure is redirected, bash > runs the code in a child process. "redirection" (instead of "pipeline") better describes a different issue, which in fact also means a subshell, in traditional Bourne shells (only). $ i=global $ for i in local; do :; done > /dev/null $ echo $i global (an example with "while read x" would be more subtle, because the variable becomes empty with an EOF.)
|
Pages: 1 Prev: can i duplicate stdin to stdout? Next: counting connection entries |