【问题标题】:How to iterate over associative arrays in Bash如何在 Bash 中迭代关联数组
【发布时间】:2011-03-07 23:05:12
【问题描述】:

基于 Bash 脚本中的关联数组,我需要对其进行迭代以获取键和值。

#!/bin/bash

declare -A array
array[foo]=bar
array[bar]=foo

我实际上不明白如何在使用 for-in 循环时获取密钥。

【问题讨论】:

  • $ declare -A array=( [foo]=bar [bar]=foo ) # 一次性初始化
  • 对于一小部分键值,您可以考虑:for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done

标签: bash associative-array key-value bash4


【解决方案1】:

欢迎使用输入关联数组2.0!

    clear
    echo "Welcome to input associative array 2.0! (Spaces in keys and values now supported)"
    unset array
    declare -A array
    read -p 'Enter number for array size: ' num
    for (( i=0; i < num; i++ ))
        do
            echo -n "(pair $(( $i+1 )))"
            read -p ' Enter key: ' k
            read -p '         Enter value: ' v
            echo " "
            array[$k]=$v
        done
    echo " "
    echo "The keys are: " ${!array[@]}
    echo "The values are: " ${array[@]}
    echo " "
    echo "Key <-> Value"
    echo "-------------"
    for i in "${!array[@]}"; do echo $i "<->" ${array[$i]}; done
    echo " "
    echo "Thanks for using input associative array 2.0!"

输出:

Welcome to input associative array 2.0! (Spaces in keys and values now supported)
Enter number for array size: 4
(pair 1) Enter key: Key Number 1
         Enter value: Value#1

(pair 2) Enter key: Key Two
         Enter value: Value2

(pair 3) Enter key: Key3
         Enter value: Val3

(pair 4) Enter key: Key4
         Enter value: Value4


The keys are:  Key4 Key3 Key Number 1 Key Two
The values are:  Value4 Val3 Value#1 Value2

Key <-> Value
-------------
Key4 <-> Value4
Key3 <-> Val3
Key Number 1 <-> Value#1
Key Two <-> Value2

Thanks for using input associative array 2.0!

输入关联数组1.0

(不支持包含空格的键和值)

    clear
    echo "Welcome to input associative array! (written by mO extraordinaire!)"
    unset array
    declare -A array
    read -p 'Enter number for array size: ' num
    for (( i=0; i < num; i++ ))
        do
            read -p 'Enter key and value separated by a space: ' k v
            array[$k]=$v
        done
    echo " "
    echo "The keys are: " ${!array[@]}
    echo "The values are: " ${array[@]}
    echo " "
    echo "Key <-> Value"
    echo "-------------"
    for i in ${!array[@]}; do echo $i "<->" ${array[$i]}; done
    echo " "
    echo "Thanks for using input associative array!"

输出:

Welcome to input associative array! (written by mO extraordinaire!)
Enter number for array size: 10
Enter key and value separated by a space: a1 10
Enter key and value separated by a space: b2 20
Enter key and value separated by a space: c3 30
Enter key and value separated by a space: d4 40
Enter key and value separated by a space: e5 50
Enter key and value separated by a space: f6 60
Enter key and value separated by a space: g7 70
Enter key and value separated by a space: h8 80
Enter key and value separated by a space: i9 90
Enter key and value separated by a space: j10 100

The keys are:  h8 a1 j10 g7 f6 e5 d4 c3 i9 b2
The values are:  80 10 100 70 60 50 40 30 90 20

Key <-> Value
-------------
h8 <-> 80
a1 <-> 10
j10 <-> 100
g7 <-> 70
f6 <-> 60
e5 <-> 50
d4 <-> 40
c3 <-> 30
i9 <-> 90
b2 <-> 20

Thanks for using input associative array!

【讨论】:

    【解决方案2】:
    declare -a arr
    echo "-------------------------------------"
    echo "Here another example with arr numeric"
    echo "-------------------------------------"
    arr=( 10 200 3000 40000 500000 60 700 8000 90000 100000 )
    
    echo -e "\n Elements in arr are:\n ${arr[0]} \n ${arr[1]} \n ${arr[2]} \n ${arr[3]} \n ${arr[4]} \n ${arr[5]} \n ${arr[6]} \n ${arr[7]} \n ${arr[8]} \n ${arr[9]}"
    
    echo -e " \n Total elements in arr are : ${arr[*]} \n"
    
    echo -e " \n Total lenght of arr is : ${#arr[@]} \n"
    
    for (( i=0; i<10; i++ ))
    do      echo "The value in position $i for arr is [ ${arr[i]} ]"
    done
    
    for (( j=0; j<10; j++ ))
    do      echo "The length in element $j is ${#arr[j]}"
    done
    
    for z in "${!arr[@]}"
    do      echo "The key ID is $z"
    done
    ~
    

    【讨论】:

      【解决方案3】:

      使用这个高阶函数来防止pyramid of doom

      foreach(){ 
        arr="$(declare -p $1)" ; eval "declare -A f="${arr#*=}; 
        for i in ${!f[@]}; do $2 "$i" "${f[$i]}"; done
      }
      

      示例:

      $ bar(){ echo "$1 -> $2"; }
      $ declare -A foo["flap"]="three four" foo["flop"]="one two"
      $ foreach foo bar
      flap -> three four
      flop -> one two
      

      【讨论】:

      • 我不确定这如何适用?末日金字塔不是纯粹的美学问题,真的只适用于面向对象的语言吗?
      • 你能解释一下吗? foreach 函数有点棘手。我不明白。
      【解决方案4】:

      您可以使用${!array[@]} 访问密钥:

      bash-4.0$ echo "${!array[@]}"
      foo bar
      

      然后,迭代键/值对很容易:

      for i in "${!array[@]}"
      do
        echo "key :" $i
        echo "value:" ${array[$i]}
      done
      

      【讨论】:

      • 我有“!” - 甚至没有注意到,没有,抱歉.. :)
      【解决方案5】:

      使用感叹号访问键:${!array[@]},使用${array[@]} 访问

      您可以像这样迭代键/值对:

      for i in "${!array[@]}"
      do
        echo "key  : $i"
        echo "value: ${array[$i]}"
      done
      

      注意在for 语句中使用引号引起的变量(加上使用@ 而不是*)。如果任何键包含空格,这是必要的。

      另一个答案的困惑来自于您的问题包括键值的“foo”和“bar”。

      【讨论】:

      • 现在如果将所有键分配给一个数组:array=(${!hash[@]})
      • @Michael-O:你需要引用参数扩展来保护可能有空格的键:array=("${!hash[@]}")
      • @DennisWilliamson,非常感谢。我没有这个想法。
      • 我们如何使用函数参数编号而不是变量?例如for i in "${!$1[@]}" ?
      • @pkaramol:从 Bash 4.3 开始,您可以使用 namerefs。示例:declare -A aa; aa['A']=a1; aa['B']=b2; aa['C']=c3; foo () { declare -n assoc=$1; for key in "${!assoc[@]}"; do echo "Key: $key; Value: ${assoc[$key]}"; done; }; foo aa。请参阅BashFAQ/006 了解一些重要信息。
      猜你喜欢
      • 2018-09-27
      • 1970-01-01
      • 2015-06-30
      • 2013-12-17
      • 2020-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多