Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash populate an array in loop

How can i populate an array in loop? I'd like to do something like that:

declare -A results

results["a"]=1
results["b"]=2

while read data; do
results[$data]=1
done

for i in "${!results[@]}"
do
  echo "key  : $i"
  echo "value: ${results[$i]}"
done

But it seems that I cannot add anything to an array within for loop. Why?

like image 316
Dejwi Avatar asked Apr 02 '12 23:04

Dejwi


2 Answers

What you have should work, assuming you have a version of Bash that supports associative arrays to begin with.

If I may take a wild guess . . . are you running something like this:

command_that_outputs_keys \
  | while read data; do
        results[$data]=1
    done

? That is — is your while loop part of a pipeline? If so, then that's the problem. You see, every command in a pipeline receives a copy of the shell's execution environment. So the while loop would be populating a copy of the results array, and when the while loop completes, that copy disappears.

Edited to add: If that is the problem, then as glenn jackman points out in a comment, you can fix it by using process substitution instead:

while read data; do
    results[$data]=1
done < <(command_that_outputs_keys)

That way, although command_that_outputs_keys will receive only a copy of the shell's execution environment (as before), the while loop will have the original, main environment, so it will be able to modify the original array.

like image 72
ruakh Avatar answered Nov 10 '22 03:11

ruakh


That seems to be working fine:

$ cat mkt.sh 
declare -A results

results["a"]=1
results["b"]=2

while read data; do
  results[$data]=1
done << EOF
3
4
5
EOF

for i in "${!results[@]}"
do
  echo "key  : $i"
  echo "value: ${results[$i]}"
done

$ ./mkt.sh 
key  : a
value: 1
key  : b
value: 2
key  : 3
value: 1
key  : 4
value: 1
key  : 5
value: 1
$ 

Ubuntu 11.10 here, bash: GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu).

like image 32
icyrock.com Avatar answered Nov 10 '22 03:11

icyrock.com