Search code examples
arraysbashdictionaryassociative-array

Bash associative array with list as value


I have to work with an output of a Java tool, which returns a map data structure that looks like HashMap<String, ArrayList<String>. I have to work with BASH and i tried to declare it as an associative array, what is very similar to a map. The declaration of the associative array in bash should be in one line, i try to do this as following.

ARRAY=(["sem1"]=("first name" "second name") ["sem2"]=("third name") ["sem3]=OTHER_LITS)

But this creates the following error:

bash: syntax error near unexpected token `('

I can define this line by line, but i want to have it in one line. How can i define a assoviative array in bash in only one line?


Solution

  • BTW, associative array, dictionary or map - all come into the one abstract data type (let's call it a dictionary).

    So, here is the solution for storing array as values in the dictionary of Bash (4+ version).

    Note, that array in Bash is a space delimited list of strings (so no any spaces inside the element, i.e. string), so we could write a quoted list:

    "firstname middlename secondname"

    as a value of the s1 key in our X dictionary:

    declare -A X=(
      ['s1']="firstname middlename secondname"
      ['s2']="surname nickname"
      ['s3']="other"
    )
    

    Now we can get the value of the s1 key as array:

    declare -a names=(${X[s1]})

    Variable names now contains array:

    > echo $names
    firstname
    
    > echo ${names[1]}
    middlename
    
    > echo ${#names[@]}
    3
    

    Finally, your question part where the strings with spaces were shown:

    "first name", "second name"

    Let's do a trick - represent a space as a special symbol sequence (it could be just one symbol), for example, double underscores:

    "first__name", "second__name"

    Declare our dictionary again, but with "escaped" spaces inside array elements:

    declare -A X=(
      ['s1']="first__name middle__name second__name"
      ['s2']="surname nickname"
      ['s3']="other"
    )
    

    In this case after we get the value of the s1 key as array:

    declare -a names=(${X[s1]})

    We need to post process our array elements to remove __ the space-replacements to the actual space symbols. To do this we simply use replace commands of Bash strings:

    > echo ${names/__/ }
    first name
    
    > echo ${names[1]/__/ }
    middle name
    
    > echo ${#names[@]}
    3