Ubuntu – What’s the best way to transform a string into an associative array

bashcommand linescripts

For the sake of exercise, I've written the few lines below in a bash script to transform a HTTP post input into an associative array. Following through on my learning, I was wondering, if there are different, maybe more elegant, ways to do this. I mean, I know there are different ways. I'm wondering which ones exist and what the advantages and disadvantages of each methods are.

Note: I'm using post as input here. The exercise however is to build a array from a multiple name/value pair string. The input could be coming from any files or other input source.

Note2: the string I'm dealing with could look like this: name=myName&age=myAge. So there are 2 delimiters. One separating name/value pairs (&) and the other separating the value from its name (=).

#!/bin/bash
read post;
declare -A myArr;
IFS_bck=$IFS;
IFS="=";
while read name value; do
  myArr[$name]=$value;
done < <(sed -rn -e 's/&/\n/g p' <<<"$post");
IFS=$IFS_bck;

P.S. I'm not willing to start a religious war. I'm simply wondering how you would do this and why you would chose your proposal over mine.

Best Answer

I would do this just using bash itself:

#!/bin/bash
read -e -p 'Enter the string: ' post
declare -A myArr

while IFS='&' read name age; do
    myArr["${name##*=}"]="${age##*=}"
done <<<"$post"

printf 'NAME: %s, AGE: %s\n' "${!myArr[@]}" "${myArr[@]}"

Here is what i get in the output:

Enter the string: name=Foo Bar&age=40
NAME: Foo Bar, AGE: 40
  • The input string is spitted on & using IFS environmental variable

  • The name and age values are parsed using parameter expansion pattern ${var##*=}

  • You can get all keys using ${!myArr[@]} and all values using ${!myArr[@]}

In practice, I don't think you would just make an associative array of one element. If you have multiple elements, replace the last printf line with a simple for construct to loop over the keys:

for key in "${!myArr[@]}"; do
    printf 'NAME: %s, AGE: %s\n' "$key" "${myArr["$key"]}"
done