Multidimensional associative arrays in Bash

前端 未结 3 1817
耶瑟儿~
耶瑟儿~ 2020-12-05 02:52

I\'m trying to create a multidimensional associative array but need some help. I have reviewed the page suggested in this SO answer but it confused me even more. So far here

相关标签:
3条回答
  • 2020-12-05 03:35
    #!/bin/bash
    declare -A PERSONS
    declare -A PERSON
    PERSON["FNAME"]='John'
    PERSON["LNAME"]='Andrew'
    PERSONS["1"]=${PERSON[@]}
    PERSON["FNAME"]='Elen'
    PERSON["LNAME"]='Murray'
    PERSONS["2"]=${PERSON[@]}
    for KEY in "${!PERSONS[@]}"; do
     TMP="${PERSONS["$KEY"]}"
     echo "$KEY - $TMP"
     **echo "${PERSON["FNAME"]}"
     echo "${PERSON["LNAME"]}**"
    done
    

    Because the original array for the separate names is still active and it can still be referenced within the for loop.

    0 讨论(0)
  • 2020-12-05 03:37

    I understand what you need. I also wanted the same for weeks. I was confused whether to use Python or Bash. Finally, exploring something else I found this Bash: How to assign an associative array to another variable name (e.g. rename the variable)?

    Here, I got to know how to assign some string and use it later as command. Then with my creativity I found solution to your problem as below:-


    #!/bin/bash
    
    declare -A PERSONS
    declare -A PERSON
    
    PERSON["FNAME"]='John'
    PERSON["LNAME"]='Andrew'
    string=$(declare -p PERSON)
    #printf "${string}\n"
    PERSONS["1"]=${string}
    #echo ${PERSONS["1"]}
    
    PERSON["FNAME"]='Elen'
    PERSON["LNAME"]='Murray'
    string=$(declare -p PERSON)
    #printf "${string}\n"
    PERSONS["2"]=${string}
    #echo ${PERSONS["2"]}
    
    for KEY in "${!PERSONS[@]}"; do
       printf "$KEY - ${PERSONS["$KEY"]}\n"
       eval "${PERSONS["$KEY"]}"
       printf "${PERSONS["$KEY"]}\n"
       for KEY in "${!PERSON[@]}"; do
          printf "INSIDE $KEY - ${PERSON["$KEY"]}\n"
       done
    done
    

    OUTPUT:-

    1 - declare -A PERSON='([FNAME]="John" [LNAME]="Andrew" )'

    declare -A PERSON='([FNAME]="John" [LNAME]="Andrew" )'

    INSIDE FNAME - John

    INSIDE LNAME - Andrew

    2 - declare -A PERSON='([FNAME]="Elen" [LNAME]="Murray" )'

    declare -A PERSON='([FNAME]="Elen" [LNAME]="Murray" )'

    INSIDE FNAME - Elen

    INSIDE LNAME - Murray


    The problem actually with multi dimensional arrays in bash and specifically in your approach is that you are assigning PERSON array values to the array element PERSONS[1] which is converted to a list and not an assoc array when you assigned it. And so it no longer will take it as 2 elements of an array as you are not keeping any info about the array data structure in your value. So, I found this hack to be sufficient with only 1 limitation that you will have to do this each time you want to do store/retrieve values. But it shall solve your purpose.

    0 讨论(0)
  • 2020-12-05 03:52

    You can't do what you're trying to do: bash arrays are one-dimensional

    $ declare -A PERSONS
    $ declare -A PERSON
    $ PERSON["FNAME"]='John'
    $ PERSON["LNAME"]='Andrew'
    $ declare -p PERSON
    declare -A PERSON='([FNAME]="John" [LNAME]="Andrew" )'
    $ PERSONS[1]=([FNAME]="John" [LNAME]="Andrew" )
    bash: PERSONS[1]: cannot assign list to array member
    

    You can fake multidimensionality by composing a suitable array index string:

    declare -A PERSONS
    declare -A PERSON
    
    PERSON["FNAME"]='John'
    PERSON["LNAME"]='Andrew'
    i=1
    for key in "${!PERSON[@]}"; do
      PERSONS[$i,$key]=${PERSON[$key]}
    done
    
    PERSON["FNAME"]='Elen'
    PERSON["LNAME"]='Murray'
    ((i++))
    for key in "${!PERSON[@]}"; do
      PERSONS[$i,$key]=${PERSON[$key]}
    done
    
    declare -p PERSONS
    # ==> declare -A PERSONS='([1,LNAME]="Andrew" [2,FNAME]="Elen" [1,FNAME]="John" [2,LNAME]="Murray" )'
    
    0 讨论(0)
提交回复
热议问题