问题描述
我正试图在bash中获得一个(键,多值)结构(某种哈希图),像这样:
I'm trying to get a (key,multiple-value) structure (some sort of hashmap) in bash, like this :
[
[ "abc" : 1, 2, 3, 4 ],
[ "def" : "w", 33, 2 ]
]
我想遍历eack密钥(某种类型的 for键入...
,并使用 map ["def",2]之类的方法获取每个值
或 map [$ key,2]
.
I'd like to iterate through eack key (some kind of for key in ...
, and get each value with something like map["def",2]
or map[$key,2]
.
我看过几个讨论单值哈希图的线程,但是关于这个问题一无所获.
I've seen a couple of threads talking about single-value hashmap, but nothing about this issue.
我可以使用 N
个数组,其中 N
是我地图中的键的数量,用行中的每个字段填充,但是我不想重复尽可能多地编写代码.
I could go with N
arrays, N
being the amount of key in my map, filled with every field in a row, but I don't want to duplicate code as much as possible.
提前谢谢!
我想通过这样的结构进行遍历:
Edit :I'd like to go through the structure with something like this :
for key in ${map[@]} do;
echo $key # "abc" then "def"
for value in ${map[$key,@]} do;
...
done
done
推荐答案
在多数组情况下使用现代bash功能:
Using modern bash features with the multiple-array case:
分配(手动):
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的范围):
Iteration (done inside a function to contain the namevar's scope):
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
,但是很容易出错-如果尝试在此模板上构建自己的实现,请非常谨慎).
This can also be done without namevars, but in an uglier and more error-prone fashion. (To be clear, I believe the code given here uses eval
safely, but it's easy to get wrong -- if trying to build your own implementation on this template, please be very cautious).
# 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"
}
...,然后以与bash兼容的方式迭代到3.x:
...and, to iterate in a way compatible with bash back through 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
与通过单个大数组过滤(给出另一个答案)相比,这在计算效率上更高-并且,当有可用的namevar时,可以说也可以使代码更简洁.
This is more computationally efficient than filtering through a single large array (the other answer given) -- and, when namevars are available, arguably results in cleaner code as well.
这篇关于遍历bash中作为键/值对中的值嵌入的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!