Dinero
Dinero

Reputation: 1160

Attempting to assign multiple variables using jq

I have a variable named $db_main_info that contains the following string

 { "host": "env-prod-blah-db.blah.us-east-1.rds.amazonaws.com", "dbname": "blahblah", "user": "foobar", "password": "foopassfoopass" }

I am doing the following

read host dbname user password < <(echo $db_main_info | jq -r '.host, .dbname, .user, .password')

After executing the above statement when i do echo $host it prints the following

env-prod-blah-db.blah.us-east-1.rds.amazonaws.com

However the other 3 variables dbname,user and password never get set. I am not sure what i am doing wrong?

I expect the variable dbname to take the value blahblah and the variable user to take the value foobar and the variable password to take the value foopassfoopass

Upvotes: 0

Views: 1076

Answers (2)

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10133

jq prints each field on a separate line, but read reads, by default, one line only. One method is to modify the default behaviour of read, by assigning the newline character to the IFS, which sets this character to be used as the field separator, and setting the line delimiter to the null string (so that newline no longer serves as a delimiter to indicate the end of line):

#!/bin/bash

db_main_info='{ "host": "env-prod-blah-db.blah.us-east-1.rds.amazonaws.com", "dbname": "blahblah", "user": "foobar", "password": "foopassfoopass" }'

IFS=$'\n' read -r -d '' host dbname user password < <(jq -r '.host, .dbname, .user, .password' <<< "$db_main_info")
echo "host=$host"
echo "dbname=$dbname"
echo "user=$user"
echo "password=$password"

Upvotes: 6

that other guy
that other guy

Reputation: 123640

You can run jq alone to see what the problem is:

$ echo "$db_main_info" | jq -r '.host, .dbname, .user, .password'
env-prod-blah-db.blah.us-east-1.rds.amazonaws.com
blahblah
foobar
foopassfoopass

There's four lines with one field each. You were assuming it was one line with four fields.

You can instead read multiple lines and assign each to the variable:

db_main_info=' { "host": "env-prod-blah-db.blah.us-east-1.rds.amazonaws.com", "dbname": "blahblah", "user": "foobar", "password": "foopassfoopass" }'

for var in host dbname user password
do
  IFS='' read -r "$var"
done < <(echo "$db_main_info" | jq -r '.host, .dbname, .user, .password')

echo "Host: $host, DB name: $dbname, user: $user, password: $password"

This results in:

Host: env-prod-blah-db.blah.us-east-1.rds.amazonaws.com, DB name: blahblah, user: foobar, password: foopassfoopass

Upvotes: 1

Related Questions