I want to fill an associative array in bash in somewhat non-trivial setup. I have a pipeline of commands to produce the required input for the array.
Here is a minimal/toy example:
declare -A mapping
seq 10 | while read i; do
key="key_$i"
val="val_$i"
echo "mapping[$key]=$val"
mapping["${key}"]="${val}"
done
echo "${mapping["key_1"]}"
echo "${mapping["key_2"]}"
In this example mapping
is changed inside while
, but these changes do not propagate into the global namespace. I think this is because while
works inside a separate subshell, thus namespaces have diverged.
In order to avoid (what I suggest) the problem with subshells, I came up with the following:
declare -A mapping
while read i; do
key="key_$i"
val="val_$i"
echo "mapping[$key]=$val"
mapping["${key}"]="${val}"
done < <(seq 10)
echo "${mapping["key_1"]}"
echo "${mapping["key_2"]}"
Thus, the generation part explicitly goes into a subshell, while the while
loop left at the top-level alone. The construction works.
My questions are: is there any better way to accomplish my goal? And, is my suggestion about subshells correct? If so, why bash uses a subshell in the first case, but not in the second?
EDIT: after little more digging, the question mostly is a duplicate of this one. A good list of options to handle the issue could be found at http://mywiki.wooledge.org/BashFAQ/024