Thanks, Phil and Jack! You've explained it.
Adam wrote:
>>> #!/bin/bash
>>> CONTENTS="xyz"
>>> N=1
>>> echo "$CONTENTS" | while read LINE ; do
>>> N=4
>>> echo N = $N
>>> done
>>> echo N is now $N
>>>
>>> [EMAIL PROTECTED] ~]$ ./d
>>> N = 4
>>> N is now
On Fri, Sep 12, 2008 at 9:56 PM, Phil M Perry <[EMAIL PROTECTED]> wrote:
>> What is the echo "$CONTENTS" | while-command supposed to do? I don't
>> think I've seen that idiom before. I suspect that it's creating some sort
>> of
>> local environment within it (piping to a new process?) so that a new "N" is
>> created just for that little bit. Does $LINE exist after the echo/loop?
>>
Nope, both N and LINE vanish after the loop. That would also explain
why it works the way I'd expect if instead of "echo | while" it's just
plain "while":
while [ $N -lt 5 ] ; do
let N=N+1
etc.
Jack Chastain wrote:
> Phil is on the right track - you are using a pipeline to create your while
> loop - which is running in a new process.
>
> ksh doesn't do this - but bash and Bourne do.
>
That would explain it -- it was suggested to me as a way to use
variables instead of temporary files -- but by someone whose experience
is with ksh, not bash. I gather that if I'm going to learn how to write
scripts for one shell, it ought to be bash, as that's the most ubuquitous.
> An interesting experiment - truss the entire script when you run it:
>
> truss ./d
>
> You should see the entry - and exit - from the subshell.
>
Mandriva doesn't seem to have 'truss'. I tried 'strace' but the
subshell didn't seem obvious.
> I haven't been able to find a way to transport the variable with this code
> but if it is needed, would suggest something along the lines of:
>
> for LINE in $CONTENTS; do
>
> This can be an issue if "$CONTENTS" contains spaces or other whitespace.
In the actual script, $CONTENTS will contain several lines and other
whitespace, something like:
CONTENTS=$(ls -d D*)
echo $CONTENTS | while read LINE ; do
{process next line of CONTENTS, assign to FOO}
RESULTS="$RESULTS
$FOO"
done
echo $RESULTS >> $OUTPUTFILE
Presumably this works under ksh.
> There must be hundreds of other options.
>
I think I'll use:
CONTENTS=$(ls -d D*)
echo $CONTENTS | while read LINE ; do
{process next line of CONTENTS, assign to FOO}
echo $FOO >> $TMP1
done
# only modify OUTPUTFILE if everything has been successful
cat $TMP1 >> $OUTPUTFILE
This does use one temporary file, but that still should be more
efficient. I'd been sending the output of 'ls' to a file, and was using
three temporary files. I'll pass this info back to the ksh programmer
too. Thanks again!
Adam
_______________________________________________
Mid-Hudson Valley Linux Users Group http://mhvlug.org
http://mhvlug.org/cgi-bin/mailman/listinfo/mhvlug
Upcoming Meetings (6pm - 8pm) MHVLS Auditorium
Sep 3 - Porkchop - The Areas of My Expertise
Oct 1 - Ubikeys
Oct 4 - Linux Fest
Nov 5 - Releasing Open Source Software
Dec 3 - TBD