[Novalug] bash weirdness
Mike Miller
mtmiller at ieee.org
Fri Apr 9 20:44:03 EDT 2010
On Fri, 2010-04-09 at 16:30 -0400, Ed James wrote:
> Chris,
>
> Try initializing the data[] variable outside/before the while
> loop.
>
> Ed James
>
> Quoting "Chris Snyder" <gopher at 3wa.org>:
>
> > Can somebody please explain to me what this bash snippet is doing? Why is my
> > array data disappearing outside of the 'while'? Bash doesn't have scoping by
> > default unless you use local or something like that. WTF?!?
> >
> > thx
> > Gopher.
> >
> > --------------------
> > #!/bin/bash
> >
> > ls | while read output; do
> > data[$i]="$output"
> > let i++
> > echo "Current array size: " ${#data[*]}
> > done
> >
> > echo "Final array size" ${#data[*]}
> >
> > --------------------
> >
> > Here's my output:
> >
> > bash y
> > Current array size: 1
> > Current array size: 2
> > Current array size: 3
> > Current array size: 4
> > Current array size: 5
> > Current array size: 6
> > Current array size: 7
> > Current array size: 8
> > Current array size: 9
> > Current array size: 10
> > Current array size: 11
> > Current array size: 12
> > Current array size: 13
> > Current array size: 14
> > Current array size: 15
> > Current array size: 16
> > Current array size: 17
> > Current array size: 18
> > Final array size 0
It's actually not scoping or initialization, your command is a pipeline,
where the entire while loop is the second command of the pipeline. From
the bash man page:
Each command in a pipeline is executed as a separate process (i.e., in a
subshell).
So even if you initialize your array first, the while loop subshell gets
the initial value, changes it inside the loop, and exits. A subshell
can never change the state of the parent shell.
If you change your while loop to read from a file it should work because
the while loop is not in a subshell now:
ls > foo
while read output; do
data[$i]="$output"
let i++
echo "Current array size: " ${#data[*]}
done < foo
echo "Final array size" ${#data[*]}
To me, the nicest looking way would be to fill in the "positional
parameters" and process the list like you would an argument list,
something like:
set -- `ls`
while [ "$1" ]; do
data[$i]="$1"
let i++
shift
done
--
mike :: mtmiller at ieee dot org
More information about the Novalug
mailing list