问题
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