I need to associate values based on this table.
KEYS VALS
---- ----
keyp val1
keyp val2
keyp val3
keyp val6
keyc val4
keym val4
keys val8
keyr val8
keyb val5
In my ksh, when a parameter is passed that is a KEY, I want to iterate through that table so that I get all the possible VALS. For example if parm_key="keyp", my iteration would yield val1, val2, val3, val6. Psuedocode:
for iLoop in "${!KEYS2VALS[@]}"
do
if [[ KEYS2VALS[iLoop] = $parm_key ]];then
print "found value match=$KEYS2VALS[iLoop].VAL"
fi
done
The output from that psuedocode should be the below if $parm_key="keyp"
found value match=val1
found value match=val2
found value match=val3
found value match=val6
Assuming you've got access to ksh93 (so we can use associative arrays) ...
NOTE: With some newer OSs /bin/ksh is ksh93 (either renamed or symlinked to ksh93); in this case ksh --version
will show a string that contains 93u
or 93u+
Start with a flat file that contains the desired key/value pairs:
# sample data file
$ cat key.vals
keyp val1
keyp val2
keyp val3
keyp val6
keyc val4
keym val4
keys val8
keyr val8
keyb val5
One possible ksh93 shell script:
$ cat kv
#!/bin/ksh93
# grab and verify an input key
parm_key=$1
[[ "${parm_key}" = '' ]] && printf "Usage: kv <parm_key>\n" && exit
# declare associative array 'keys2vals'
unset keys2vals
typeset -A keys2vals
# load the key/value pairs into the associative array 'keys2vals'
while read -r key val
do
keys2vals[${key}]="${keys2vals[${key}]} ${val}"
done < key.vals
# for debug purposes only: display array
printf "All key/value pairs:\n\n"
for key in ${!keys2vals[@]}
do
echo "key=${key} : value=${keys2vals[${key}]}"
done
echo ""
# print the values associated with ${parm_key}
printf "All values for key = ${parm_key}:\n\n"
for val in ${keys2vals[${parm_key}]}
do
echo "found value match=${val}"
done
The script in action:
$ kv
Usage: kv <parm_key>
$ kv keyp
All key/value pairs:
key=keyb : value= val5
key=keyc : value= val4
key=keym : value= val4
key=keyp : value= val1 val2 val3 val6
key=keyr : value= val8
key=keys : value= val8
All values for key = keyp:
found value match=val1
found value match=val2
found value match=val3
found value match=val6
# commenting out the debug loop ...
$ kv keyb
All values for key = keyb:
found value match=val5
$ kv keyc
All values for key = keyc:
found value match=val4
$ kv keym
All values for key = keym:
found value match=val4
$ kv keyr
All values for key = keyr:
found value match=val8
$ kv keys
All values for key = keys:
found value match=val8
I managed to get 2-dimensional associative arrays working for this example:
First, let's put that data into a file
$ cat table.txt
KEYS VALS
---- ----
keyp val1
keyp val2
keyp val3
keyp val6
keyc val4
keym val4
keys val8
keyr val8
keyb val5
We'll use an associative array named "table"
typeset -A table
Now, let's populate the array. The tricky bit here is that we need to declare that each element of the array is itself an associative array. We need to do this when we encounter a key that is not in "table":
i=0
sed '1,2d' table.txt | while read -r key value; do
[[ -z "${table[$key]+not set}" ]] && typeset -A table[$key]
table[$key][$value]=$((++i))
done
Now, let's see what we have in the table array
for key in "${!table[@]}"; do
for subkey in "${!table[$key][@]}"; do
printf "%s\t%s\t%s\n" "$key" "$subkey" "${table[$key][$subkey]}"
done
done
keyb 0
keyb val5 9
keyc 0
keyc val4 5
keym 0
keym val4 6
keyp 0
keyp val1 1
keyp val2 2
keyp val3 3
keyp val6 4
keyr 0
keyr val8 8
keys 0
keys val8 7
All is well, except that every top-level key also has a subkey "0". That looks odd, but I think that's how variables are implemented in ksh. Even simple scalar variables can be referenced as an array with index 0:
$ foo=bar
$ echo "$foo"
bar
$ echo "${foo[0]}"
bar
$ printf "%s\n" "${!foo[@]}"
0
To the heart of the question: retrieve the values for a particular key:
parm_key="keyp"
typeset -a values
for val in "${!table[$parm_key][@]}"; do
[[ $val = "0" ]] || values+=("$val")
done
printf "%s\n" "${values[@]}"
val1
val2
val3
val6
I just realized this is quite overcomplicated. We don't need an associative array of associative arrays. we want an associative array of indexed arrays:
$ unset table
$ typeset -A table
$ sed '1,2d' table.txt | while read -r key value; do table[$key]+=("$value"); done
$ printf "%s\n" "${!table[@]}"
keyb
keyc
keym
keyp
keyr
keys
$ for key in "${!table[@]}"; do for val in "${table[$key][@]}"; do printf "%s\t%s\n" "$key" "$val"; done; done
keyb val5
keyc val4
keym val4
keyp val1
keyp val2
keyp val3
keyp val6
keyr val8
keys val8
$ printf "%s\n" "${table[$parm_key][@]}"
val1
val2
val3
val6
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.