1

I am getting some data returned from a command line tool and would like to fill an associative array with the data. I can alter the format of the data returned, but how must it be to the associative array?

content="[key1]=val1 [key2]=val2" # How should this be formatted?

declare -A hashTable
hashTable=($content) # How to set it?

declare -p hashTable
2
  • 2
    @Adamarla: Could you provide how the command-line tool actually returns the output? It is not easy to understand from a variable Commented Feb 28, 2018 at 13:05
  • 1
    Can the value take spaces? Unless you show some actual values, it will tough to parse it Commented Feb 28, 2018 at 13:06

3 Answers 3

1

The best way to do this (which requires bash 4.4 or later) is to have your command return a string alternating keys and values, each terminated by a null character. You can then use readArray to parse this into an indexed array, then build your associative array from that.

$ readArray -t -d '' foo < <(printf 'key1\0value1\0key2\0value2\0')
$ declare -p foo
declare -a foo=([0]="key1" [1]="value1" [2]="key2" [3]="value2")
$ for ((i=0; i < ${#foo[@]}; i+=2)); do
>  hashTable[${foo[i]}]=${foo[i+1]}
> done
$ declare -p hashTable
declare -A hashTable=([key2]="value2" [key1]="value1" )

bash 4.4 is required for the -d option to readArray. In earlier 4.x releases, you can use a string with embedded newlines, but that precludes your keys or values from themselves containing newlines.

(Note that in the assignments to hashTable, you can safely leave both ${foo[i]} and ${foo[i+1]} unquoted, as neither the key nor the value will undergo word splitting or pathname expansion. It doesn't hurt to quote them if you wish, though.)

Sign up to request clarification or add additional context in comments.

1 Comment

I have no idea why this answer never got an upvote, but it's best for me!
0

If you master content and understand well bash parsing, for example not coming from exernal input

eval "hashTable=($content)"

otherwise you have to parse it to ensure no injection (as eval reinterpret data as code, bash expression), imagine content contains echo given as example

content=');echo hey;x=('

maybe easier to split the content :

hashTable=()
tmp=$content
while [[ $tmp = *\[* ]] && tmp=${tmp#*\[} || tmp=; [[ $tmp ]]; do
    cur=${tmp%%\[*};
    val=${cur#*\]=};
    hashTable[${cur%%\]=*}]=${val%${val##*[![:space:]]}}
done

Comments

0

If you accept to format the output of the first command like this

key1=value1 key2=value2

without spaces in value2 and without '=', then you can try this code:

#!/bin/bash
content="key1=val1 key2=val2"   

declare -A hashTable

for pair in $content ; do 
  key=${pair%=*}        # take the part of the string $pair before '='
  value=${pair/#*=/}    # take the part of the string $pair after '='
  hashTable[$key]=$value
done

for K in "${!hashTable[@]}";  do echo hashTable\[$K\]=${hashTable[$K]}; done

1 Comment

Iterating over unquoted $content is not going to be safe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.