bash question: command substitution is eating my arrays!

Karl Auer kauer at biplane.com.au
Sun Oct 27 16:57:58 UTC 2019


The script below displays some (for me) surprising behaviour.

I want a function to update an array and return some output[1].

The first loop, which captures the function's output, does not work -
inside the function it clearly does update the array, but outside the
function the array stays empty. Note that it contains no values after
the first loop completes.

The second loop works as expected in that the array collects all the
test values, and still has them after the second loop completes - but
the calls don't capture the function's output.

The ONLY difference between the loops is that the first captures the
function's output.

What am I missing? Why does capturing the output from the function seem
to clear the array?

Here is the script:

    #!/bin/bash

    declare -A TEST

    add_element() {
       KEY="$1"
       local VALUE="$KEY-floop"

       TEST["$KEY"]="$VALUE"
       echo "$VALUE"
       echo "This: TEST[$KEY] = ${TEST["$KEY"]} Count: ${#TEST[@]}" >&2
    }

    for i in one two three four ; do
    {
       X=$(add_element $i)
    }
    done
    echo "After first loop, count is ${#TEST[@]}"
    echo "Values: ${!TEST[@]}"
    echo

    for i in one two three four ; do
    {
       add_element $i
    }
    done
    echo "After second loop, count is ${#TEST[@]}"
    echo "Values: ${!TEST[@]}"

This is the output from the above:

    This: TEST[one] = one-floop Count: 1
    This: TEST[two] = two-floop Count: 1
    This: TEST[three] = three-floop Count: 1
    This: TEST[four] = four-floop Count: 1
    After first loop, count is 0
    Values: 

    one-floop
    This: TEST[one] = one-floop Count: 1
    two-floop
    This: TEST[two] = two-floop Count: 2
    three-floop
    This: TEST[three] = three-floop Count: 3
    four-floop
    This: TEST[four] = four-floop Count: 4
    After second loop, count is 4
    Values: four one two three

Regards, K.

[1] I want to cache some values, so the function I really want will be
passed a key. If the key exists in the global array the function should
output the value. If the key is not in the array, the function should
go find the appropriate value for the key, put it in the array, and
then output the value. Getting the value for a given key is very
costly, hence the desire to cache them. While I could build the entire
cache first, that would be a major change to my script's logic and a
last resort, not least because it would have to cache all the possible
keys, though any given run will only need a few of them. 

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Karl Auer (kauer at biplane.com.au)
http://www.biplane.com.au/kauer
http://twitter.com/kauer389

GPG fingerprint: 8D08 9CAA 649A AFEF E862 062A 2E97 42D4 A2A0 616D
Old fingerprint: A0CD 28F0 10BE FC21 C57C 67C1 19A6 83A4 9B0B 1D75






More information about the ubuntu-users mailing list