How to Extract Value from JSON Contained in a Variable Using Jq in Bash

How to extract value from json contained in a variable using jq in bash

You may use this:

json_val='{"code":"lyz1To6ZTWClDHSiaeXyxg","redirect_to":"http://example.com/client-redirect-uri?code=lyz1To6ZTWClDHSiaeXyxg"}'
code_val=$(jq -r '.code' <<< "$json_val")
echo "$code_val"

lyz1To6ZTWClDHSiaeXyxg

Note following changes:

  • Wrap complete json string in single quotes
  • use of $(...) for command substitution
  • Use of <<< (here-string) to avoid a sub-shell creation

PS: If you're getting json text from a curl command and want to store multiple fields in shell variables then use:

read -r code_val redirect_to < <(curl ... | jq -r '.code + "\t" + .redirect_to')

Where ... is your curl command.

Extract value of json-like variable in bash

If

echo $CLUSTER

gives you

{ "ClusterId": "j-9YWMBYN98LN7" }

then

ID=$(awk  'BEGIN{FS="\""}{print $4}' <<< "${CLUSTER}")

should do it.

echo "$ID"
j-9YWMBYN98LN7

Retrieving value from JSON object in bash using JQ

NAME=$(jq -r '.ConfigurationRecorders[].name' <<<"$CONFIG_RECORDER")

<<< is known as here-string.

-r removes the quotes in the result.

[] in the jq query is necessary as ConfigurationRecorders is a JSON array.

$( … ) is just an other form of command substitution than backticks. I prefer this one as it is more readable to me.

Extract JSON value to shell variable using jq

In order to handle all values properly, you need to use the declare command to incorporate the output of jq into an array assignment.

Here's some input with some corner cases to worry about: whitespace, a newline, and a glob character.

$ cat input.json
[
{"id":10,
"list_file":[
"/var/a b.txt",
"/dev/c\nd.txt",
"*"]}
]

A jq command that extracts and outputs properly quoted strings for use by the shell:

$ $ jq -r '.[] | .list_file[] | @sh' input.json
'/var/a b.txt'
'/dev/c
d.txt'
'*'

And a shell command that can make use of the output:

$ declare -a "x=($(jq -r '.[] | .list_file[] | @sh' input.json))"

Proof that it worked properly:

$ printf '==%s==\n' "${x[@]}"
==/var/a b.txt==
==/dev/c
d.txt==
==*==

Extract values from JSON objects and assign them to shell variables in a loop

You can output each email-ID pair as a comma separated list from JQ, and use read them into variables in a while loop like so:

while IFS=',' read -r email id; do
echo "$email"
echo "$id"
done <<EOF
$(jq -r '.values[] | "\(.email),\(.id)"' file)
EOF

select specific values from json & convert into bash variables

If instead of trying to extract variable names from the JSON, you populate an associate array with the names as keys, it's pretty straightforward.

#!/usr/bin/env bash

declare -A sauces
while IFS=$'\001' read -r name value; do
sauces[$name]=$value
done < <(jq -r '.env_vars[] | "\(.name)\u0001\(.value)"' saucy.json)

for name in "${!sauces[@]}"; do
echo "$name is ${sauces[$name]}"
done

prints out

SAUCE_VALUE is sauceValue
SAUCE_KEY is sauceKey

Using jq to fetch key value from json output

You need to combine filters by means of | operator:

$ jq -r '.[] | .[] | .name' test.json 
rhel6.6
rhel7

The first .[] fetches repositories array. The next .[] fetches all the items of the repositories array. Finally, .name extracts properties from the array items(objects).

Note, the first .[] works on object because it is a documented feature:

.[]
If you use the .[index] syntax, but omit the index entirely, it
will return all of the elements of an array...

You can also use this on an object, and it will return all the
values of the object.

Parse JSON data in variables using JQ

You can use bash arrays to store your values:

ruleId=($($whitelist | jq -r '.[].ruleId'))
alert=($($whitelist | jq -r '.[].alertName'))
...

and then iterate over them. Example:

for (( i = 0; i < "${#ruleId[@]}"; i++ )); do
id="${ruleId[i]}"
al="${alert[i]}"
...
echo "$(curl --data-urlencode "ruleId=$id" ...
done

This works if and only if the values returned by your commands are single words (no spaces in them) or they are properly quoted. If you have more complex values you cannot simply assign them to an array with array=($(command)). You would get more cells than values in your array.

multi extract values with JQ

Using tr like this is a bit hacky, but:

$ cat input

{
"range": "Sheet!A2:B100",
"majorDimension": "ROWS",
"values": [
[
"customer1_name",
"customer1@email.com",
"customer1_phone",
"customer1_city"
],
[
"customer2_name",
"customer2@email.com",
"customer2_phone",
"customer2_city"
]
]
}
$ jq -rc '.values[]' input | tr -d '["]' | while IFS=, read var1 var2 var3 var4; do echo "$var1 $var2 $var3 $var4"; done
customer1_name customer1@email.com customer1_phone customer1_city
customer2_name customer2@email.com customer2_phone customer2_city

You can also do:

$ jq -rc '.values[][]' input | while read name; read email; read phone; read city; do echo "$name $email $phone $city"; done;
customer1_name customer1@email.com customer1_phone customer1_city
customer2_name customer2@email.com customer2_phone customer2_city


Related Topics



Leave a reply



Submit