迭代bash中作为键/值对中的值嵌入的列表

迭代bash中作为键/值对中的值嵌入的列表,bash,dictionary,Bash,Dictionary,我试图在bash中获得一个(键、多值)结构(某种hashmap),如下所示: [ [ "abc" : 1, 2, 3, 4 ], [ "def" : "w", 33, 2 ] ] for key in ${map[@]} do; echo $key # "abc" then "def" for value in ${map[$key,@]} do; ... done done 我希望遍历每个键(某种类型的用于输入…,并使用map[“def”,2]或m

我试图在bash中获得一个(键、多值)结构(某种hashmap),如下所示:

[   
  [ "abc" : 1, 2, 3, 4 ],
  [ "def" : "w", 33, 2 ]    
]
for key in ${map[@]} do;
  echo $key # "abc" then "def"
  for value in ${map[$key,@]} do;
    ...
  done
done
我希望遍历每个键(某种类型的
用于输入…
,并使用
map[“def”,2]
map[$key,2]
之类的内容获取每个值

我已经看到几个线程讨论了单值hashmap,但没有讨论这个问题

我可以使用
N
数组,
N
是我的映射中的键的数量,用一行中的每个字段填充,但我不想尽可能多地重复代码

提前谢谢

编辑: 我想用这样的东西来介绍一下结构:

[   
  [ "abc" : 1, 2, 3, 4 ],
  [ "def" : "w", 33, 2 ]    
]
for key in ${map[@]} do;
  echo $key # "abc" then "def"
  for value in ${map[$key,@]} do;
    ...
  done
done

这个宣言有点难看

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

迭代:有助于保留单独的“键”数组:

然后


这个宣言有点难看

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

迭代:有助于保留单独的“键”数组:

然后


将现代bash功能与多阵列案例结合使用:


作业(手册):

分配(方案性):

迭代(在函数内完成以包含namevar的作用域):


这也可以在没有命名变量的情况下完成,但会以更丑陋、更容易出错的方式完成(要清楚,我相信这里给出的代码安全地使用了
eval
,但很容易出错——如果试图在此模板上构建自己的实现,请非常小心)

…并且,要以与bash兼容的方式通过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可用时,可以说还会产生更干净的代码。

将现代bash功能用于多数组情况:


作业(手册):

分配(方案性):

迭代(在函数内完成以包含namevar的作用域):


这也可以在没有命名变量的情况下完成,但会以更丑陋、更容易出错的方式完成(要清楚,我相信这里给出的代码安全地使用了
eval
,但很容易出错——如果试图在此模板上构建自己的实现,请非常小心)

…并且,要以与bash兼容的方式通过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可用时,可以说也会产生更干净的代码。

有什么原因需要使用bash吗?它确实不太适合这样做。是的,我知道,但我真的需要bash:)可能是重复的好吧,它不是那么优雅(我没想到解决方案会是这样)。我试试看!哪个版本的bash?如果是4.3或更高版本,则可以使用namevar,这使得多数组实现更易于处理。是否有理由使用bash?它真的不太适合这个。是的,我知道,但我真的需要在这一点上重击:)可能重复的好,它不是那么优雅(我没想到的解决方案是)。我试试看!哪个版本的bash?如果是4.3或更高版本,则可以使用名称变量,这使得多数组实现更易于处理。谢谢,但请参见上面的编辑!迭代${map[@]}(使用单个循环)将输出每个值。已更新。不幸的是,复杂的bash数据结构意味着复杂的代码谢谢,但是请参见我上面的编辑!迭代${map[@]}(使用单个循环)将输出每个值。已更新。不幸的是,复杂的bash数据结构意味着复杂的编解码器、完整的答案、漂亮的帖子和漂亮的解释。你应该得到1000谢谢!非常感谢。完整的答案,漂亮的帖子,漂亮的解释。你应该得到1000谢谢!非常感谢。
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
# 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"
}
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