遍历bash中作为键/值对中的值嵌入的列表 [英] Iterate over lists embedded as values in key/value pairs in bash

查看:60
本文介绍了遍历bash中作为键/值对中的值嵌入的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图在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中作为键/值对中的值嵌入的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆