我正在尝试在bash中获取(键,多值)结构(某种类型的hashmap),如下所示:
[
[ "abc" : 1, 2, 3, 4 ],
[ "def" : "w", 33, 2 ]
]
我想遍历eack密钥(某种for key in ...
),并使用map["def",2]
或map[$key,2]
等内容获取每个值。
我见过几个关于单值hashmap的线程,但没有关于这个问题。
我可以使用N
数组,N
是我的地图中的键数量,填充连续的每个字段,但我不想尽可能多地复制代码。
提前致谢!
编辑: 我想通过这样的结构来完成结构:
for key in ${map[@]} do;
echo $key # "abc" then "def"
for value in ${map[$key,@]} do;
...
done
done
答案 0 :(得分:2)
在多阵列案例中使用现代bash功能:
作业(手册):
map_abc=( 1 2 3 4 )
map_def=( w 33 2 )
作业(程序化):
append() {
local array_name="${1}_$2"; shift; shift
declare -g -a "$array_name"
declare -n array="$array_name" # BASH 4.3 FEATURE
array+=( "$@" )
}
append map abc 1 2 3 4
append map def w 33 2
迭代(在函数内部完成,包含namevar' s范围):
iter() {
for array in ${!map_@}; do
echo "Iterating over array ${array#map_}"
declare -n cur_array="$array" # BASH 4.3 FEATURE
for key in "${!cur_array[@]}"; do
echo "$key: ${cur_array[$key]}"
done
done
}
iter
这也可以在没有namevars的情况下完成,但是更丑陋,更容易出错。 (要清楚,我相信此处给出的代码安全地使用eval
,但它很容易出错 - 如果尝试在此模板上构建自己的实现,请非常谨慎。)
# Compatible with older bash (should be through 3.x).
append() {
local array_name="${1}_$2"; shift; shift
declare -g -a "$array_name"
local args_str cmd_str
printf -v args_str '%q ' "$@"
printf -v cmd_str "%q+=( %s )" "$array_name" "$args_str"
eval "$cmd_str"
}
...并且,以与3.x相反的方式迭代迭代:
for array in ${!map_@}; do
echo "Iterating over array ${array#map_}"
printf -v cur_array_cmd 'cur_array=( ${%q[@]} )' "$array"
eval "$cur_array_cmd"
for key in "${!cur_array[@]}"; do
echo "$key: ${cur_array[$key]}"
done
done
这比通过单个大型数组进行过滤计算效率更高(给出的另一个答案) - 并且,当名称变量可用时,可以说代码也更清晰。
答案 1 :(得分:1)
DO-能。声明有点难看
declare -A map=(
[abc,0]=1
[abc,1]=2
[abc,2]=3
[abc,3]=4
[def,0]=w
[def,1]=33
[def,2]=2
)
key="def"
i=1
echo "${map[$key,$i]}" # => 33
迭代:有助于保留一个单独的"键":
keys=(abc def)
然后
for key in "${keys[@]}"; do
echo "$key"
for idx in "${!map[@]}"; do
if [[ $idx == $key,* ]]; then
n=${idx##*,}
printf "\t%s\t%s\n" "$n" "${map["$idx"]}"
fi
done
done
abc
0 1
1 2
2 3
3 4
def
1 33
0 w
2 2