Shell tips and tricks

VirginSnow at vfemail.net VirginSnow at vfemail.net
Thu Nov 1 12:25:27 EDT 2007


> Date: Wed, 31 Oct 2007 13:35:07 -0400 (EDT)
> From: "Steven W. Orr" <steveo at syslang.net>

> On Wednesday, Oct 31st 2007 at 13:13 -0000, quoth Paul Lussier:

> foo=44
> p1 | while read line
> do
>     dosomething
>     foo=$((foo + 1))
> done
> echo "foo = $foo"
> 
> Given (let's say) 5 lines of output from p1, what will it print?

Note that the following will do "what you'd expect":

 foo=44
 while read line; do
  foo=$((foo + 1))
 done < <(p1)
 echo "foo = $foo"

The difference is that this (this whole example) is run in the same
subshell.  When you use "|", the "while...do...done" runs in a
different subshell... which disappears by the time bash gets around to
running 'echo $foo".

One trick which I've used to get around this is:

 foo=44
 p1 | while read line
 do
     dosomething > /dev/null 2>&1 # redirect output somewhere safe
     foo=$((foo + 1))
     echo MAGIC "$foo" #use magic just in case unexpected output reaches stdout
 done | grep ^MAGIC | tail -n 1 | {
  read magic foo
  echo "foo = $foo"
  # the rest of the code which needs access to foo
 }



More information about the gnhlug-discuss mailing list