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

a 夏天 提交于 2021-02-08 02:17:19

问题


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

回答1:


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



回答2:


Once you key your array names with -, there isn't a direct way to identify the count of occurrences of the string past the - character.

One way would be to use additional tools to identify the count. The "${!shapingTimes[@]}" prints all the keys of the array and sort -ut- k2 goes a unique sort based on the 2nd field following the - delimiter, which is piped to wc -l to get the line count.

printf '%s\n' "${!shapingTimes[@]}" | sort -ut- -k2 | wc -l
3



回答3:


Same as @Cyrus's solution, but with no loop and no sub-shell:

#!/usr/bin/env bash

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

# Populate simple array with keys only
declare -a shapingTimesKeys=("${!shapingTimes[@]}")

# Create associative array entries declaration string
# populated by prefix stripped keys
printf -v _str '[%q]= ' "${shapingTimesKeys[@]/#[0-9]*-/}"

# Declare the stripped keys associative array using
# the string populated just above
declare -A shapingTimesHash="($_str)"

printf 'Found %d keys:\n' "${#shapingTimesHash[@]}"
printf '%q\n' "${!shapingTimesHash[@]}"


来源:https://stackoverflow.com/questions/63532910/bash-count-total-number-of-keys-in-an-associative-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!