1

The question is exactly the opposite of Constructing a json hash from a bash associative array. Given the following JSON:

{
    "a": "z",
    "b": "y",
    "c": "x"
}

I would like to have an associative Bash array.

Fleshgrinder
  • 15,703
  • 4
  • 47
  • 56

2 Answers2

3

A NUL-delimited stream is the safest approach:

input='{"a":"z","b":"y","c":"x"}'
declare -A data=()

while IFS= read -r -d '' key && IFS= read -r -d '' value; do
    data[$key]=$value
done < <(jq -j 'to_entries[] | (.key, "\u0000", .value, "\u0000")' <<<"$input")

Note the use of jq -j, which suppresses quoting (like -r), but also suppresses the implicit newline between items, letting us manually insert a NUL instead.

See the discussion in https://github.com/stedolan/jq/issues/1271 (a ticket explicitly requesting a NUL-delimited output mode), wherein this idiom was first suggested.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
-4

You can do it like this :

while IFS=':' read k v 
do 
    dict[$k]="$v"
done <<< "$( sed -E "s/(\"|,|{|})//g; /^ *$/d; s/^ *//g" input.txt )"

echo "The value of key 'a' is : ${dict[a]}"

Hope it helps you!

Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
  • This works only for JSON formatted exactly as originally given, and only with a `sed` having the non-POSIX-defined `-E` argument. Your JSON has more than one key/value pair on a single line? Won't work. Your JSON has spaces inside the key names or values? Won't work. Your JSON has backslash-escaped literal quotes? Won't work. Your JSON has literal `{`s inside of the strings? They disappear. Etc. – Charles Duffy Nov 22 '19 at 19:16
  • Yeah. I know. But all of those cases are not the input given in the question. As far as the given input is what shown, it will work. – Matias Barrios Nov 22 '19 at 19:18
  • If the OP only wanted something that worked for the specific input in the question, then you could just answer `declare -A dict=( [a]="z" [b]="y" [c]="x" )`. Obviously that's useless/absurd; an answer needs to be good *generally*, not only for the single sample input. – Charles Duffy Nov 22 '19 at 19:23
  • This discussion could go on forever and I know my answer would work only for his very specific use case. But for what he is trying to achieve I can imagine he has a very simple goal in mind, otherwise why would you do this using Bash and JQ? Why does he want to use totally inappropriate tools for the task? Because OP surely just wants a quick and dirty solution to solve a specific task and move on to something else. If he really wanted a solid way to handle json data he would be using some programming language and not command line magic to begin with. – Matias Barrios Nov 22 '19 at 19:28
  • A bash associative array can handle *any* `map[string]string`, so long as both the keys and values are C strings (which is to say, containing no NULs). `jq`, similarly, can handle *any* valid JSON -- it's a quite powerful programming language in its own right, and for that matter considerably more powerful than bash insofar as nested data structure manipulation is called for. Which is to say -- there are domain limitations implied by the tools selected, sure; but that's not a reason or excuse for adding your own arbitrary limitations on top, *especially* without disclosing them. – Charles Duffy Nov 22 '19 at 21:38