How can I map an unknown value alongside other known values in bash using an associative array, so that:
#!/bin/bash
array=("foo" "foo" "bar" "something else" "also something else" "bar")
declare -A map
map["foo"]="1"
map["bar"]="2"
map[unknown]="?"
for KEY in "${array[@]}"; do
echo ${map[$KEY]}
done
outputs:
1
1
2
?
?
2
I do not know in which index my element is located, nor the length of the array to be mapped. I have tried doing map[${array[@]}]="?" before setting the other values, but this does not work
See Parameter Expansion in bash man page:
man -Pless\ +/parameter:-word bash${parameter:-word} Use Default Values. If parameter is unset or null, the expan‐ sion of word is substituted. Otherwise, the value of parameter is substituted.
So
#!/bin/bash
array=("foo" "foo" "bar" "something else" "also something else" "bar")
declare -A map
map["foo"]="1"
map["bar"]="2"
for key in "${array[@]}";do
printf '%-20s -> %s\n' "$key" "${map["$key"]:-?}"
done
Will produce:
foo -> 1
foo -> 1
bar -> 2
something else -> ?
also something else -> ?
bar -> 2
But, if you really want to use map[unknown], you could:
#!/bin/bash
array=("foo" "foo" "bar" "something else" "also something else" "bar")
declare -A map="( ["foo"]="1" ["bar"]="2" ["unknown"]="?" )"
for key in "${array[@]}";do
printf '%-20s -> %s\n' "$key" "${map["$key"]:-${map["unknown"]}}"
done
This will produce same output!
Note: you could even use "default to variable, with default":
echo "${map["$key"]:-${map["unknown"]:-?}}"
This will print
map["$key"], or if not exist,
map["unknown"], or if not exist,
?.map your array, using printfarray=("foo" "foo" "bar" "something else" "also something else" "bar")
declare -A map=( ["foo"]="1" ["bar"]="2" ["unknown"]="?" )
printf -v mapStr '"${map["%s"]:-${map["unknown"]}}" ' "${array[@]}"
declare -a "mappedArray=($mapStr)"
echo "${mappedArray[*]@Q}"
'1' '1' '2' '?' '?' '2'
Then
printf -v mapStr '%-20s -> %%s\n' "${array[@]}"
printf "$mapStr" "${mappedArray[@]}"
foo -> 1
foo -> 1
bar -> 2
something else -> ?
also something else -> ?
bar -> 2
mapA2Array () {
if [[ $1 == -A ]]; then
local -n _map=$2
shift 2
else
local -n _map=map
fi
local _resArry=$1
shift
local _mapStr
printf -v _mapStr '"${_map["%s"]:-${_map["unknown"]}}" ' "$@"
declare -ga "$_resArry=($_mapStr)"
}
declare -A map="( ["foo"]="1" ["bar"]="2" ["unknown"]="?" )"
mapA2Array tstResult foo foo bar 'something else' 'also something else' bar
declare -p tstResult
declare -a tstResult=([0]="1" [1]="1" [2]="2" [3]="?" [4]="?" [5]="2")
declare -A otherMap=( ["foo"]="Hello world." ["bar"]="42" ["unknown"]="?" )
mapA2Array -A otherMap tstResult foo foo bar 'something else' 'also something else' bar
declare -p tstResult
tstResult=([0]="Hello world." [1]="Hello world." [2]="42" [3]="?" [4]="?" [5]="42")
But using this way could lead to security issues!
See Warning: limitation at end of Array elements in sed operation