Search code examples
arraysbashassociative-array

Bash: Count total number of keys in an associative array?


Consider the associative array below:

declare -A shapingTimes
 shapingTimes=([0-start]=15 [0-stop]=21 [0-anotherkey]=foo)
shapingTimes+=([1-start]=4  [1-stop]=6  [1-anotherkey]=bar)
shapingTimes+=([2-start]=9  [2-stop]=11 [2-anotherkey]=blah)

Is there a way to find the total number of keys used per entry in an array? (Is this per 'index' in an array?)

For example, how to count: [start], [stop], [anotherkey] as = 3 keys?

At the moment I'm using the hardcoded value (3) from this code I found (as below) that does the job fine, but I'm wondering if this can be achieved dynamically?

totalshapingTimes=$((${#shapingTimes[*]} / 3))

I've found these variables that return various array aspects, but not the total number of keys.

echo "All of the items in the array:" ${shapingTimes[*]}
echo "All of the indexes in the array:" ${!shapingTimes[*]}
echo "Total number of items in the array:" ${#shapingTimes[*]}
echo "Total number of KEYS in each array entry:" #???

Desired output:

All of the items in the array: 21 6 11 blah 15 4 bar 9 foo
All of the indexes in the array: 0-stop 1-stop 2-stop 2-anotherkey 0-start 1-start 1-anotherkey 2-start 0-anotherkey
Total number of items in the array: 9
Total number of KEYS in each array entry: 3

Solution

  • declare -A shapingTimes
    shapingTimes=([0-start]=15 [0-stop]=21 [0-anotherkey]=foo)
    shapingTimes+=([1-start]=4  [1-stop]=6  [1-anotherkey]=bar)
    shapingTimes+=([2-start]=9  [2-stop]=11 [2-anotherkey]=blah)
    
    # output all keys
    for i in "${!shapingTimes[@]}"; do echo $i; done
    

    Output:

    1-start
    2-stop
    1-stop
    0-start
    2-start
    2-anotherkey
    1-anotherkey
    0-stop
    0-anotherkey
    

    # Leading numbers and "-" removed:
    for i in "${!shapingTimes[@]}"; do echo ${i/#[0-9]*-/}; done
    

    Output:

    start
    stop
    stop
    start
    start
    anotherkey
    anotherkey
    stop
    anotherkey
    

    # put shortend keys in new associative array
    declare -A hash
    for i in "${!shapingTimes[@]}"; do hash[${i/#[0-9]*-/}]=""; done
    echo "${#hash[@]}"
    

    Output:

    3