asidd
asidd

Reputation: 3291

Passing bash variable to jq

I have written a script to retrieve certain value from file.json. It works if I provide the value to jq select, but the variable doesn't seem to work (or I don't know how to use it).

#!/bin/sh

#this works ***
projectID=$(cat file.json | jq -r '.resource[] | select(.username=="[email protected]") | .id')
echo "$projectID"

[email protected]

#this does not work *** no value is printed
projectID=$(cat file.json | jq -r '.resource[] | select(.username=="$EMAILID") | .id')
echo "$projectID"

Upvotes: 272

Views: 300422

Answers (12)

focus zheng
focus zheng

Reputation: 380

it is simple to filter with the variable you set.My case is test on jq-1.6

projectID=$(cat file.json | jq -r ".resource[] | select(.username=="$EMAILID") | .id")"

Upvotes: 0

OfusJK
OfusJK

Reputation: 724

All solution above is failed, I got Success from below using one equal '=' not two '==' in select

shell_script | sed '1d'|  jq --arg VAR ${SHELL_VAR} -cC '.[]|select(.branch = $VAR).branch'

Upvotes: 2

Gilles Quénot
Gilles Quénot

Reputation: 184955

It's a quote issue, you need :

projectID=$(
  cat file.json | jq -r ".resource[] | select(.username==\"$EMAILID\") | .id"
)

If you put single quotes to delimit the main string, the shell takes $EMAILID literally.

"Double quote" every literal that contains spaces/metacharacters and every expansion: "$var", "$(command "$var")", "${array[@]}", "a & b". Use 'single quotes' for code or literal $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. See
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words

Upvotes: 21

peak
peak

Reputation: 116640

Consider also passing in the shell variable (EMAILID) as a jq variable (here also EMAILID, for the sake of illustration):

   projectID=$(jq -r --arg EMAILID "$EMAILID" '
        .resource[]
        | select(.username==$EMAILID) 
        | .id' file.json)

Postscript

For the record, another possibility would be to use jq's env function for accessing environment variables. For example, consider this sequence of bash commands:

[email protected]  # not exported
EMAILID="$EMAILID" jq -n 'env.EMAILID'

The output is a JSON string:

"[email protected]"

shell arrays

Unfortunately, shell arrays are a different kettle of fish. Here are two SO resources regarding the ingestion of such arrays:

JQ - create JSON array using bash array with space

Convert bash array to json array and insert to file using jq

Upvotes: 413

Ashish Sharma
Ashish Sharma

Reputation: 672

I also faced same issue of variable substitution with jq. I found that --arg is the option which must be used with square bracket [] otherwise it won't work.. I am giving you sample example below:

RUNNER_TOKEN=$(aws secretsmanager get-secret-value --secret-id $SECRET_ID | jq '.SecretString|fromjson' | jq --arg kt $SECRET_KEY -r '.[$kt]' | tr -d '"')

Upvotes: 1

Junaid
Junaid

Reputation: 3945

In case where we want to append some string to the variable value and we are using the escaped double quotes, for example appending .crt to a variable CERT_TYPE; the following should work:

$ CERT_TYPE=client.reader
$ cat certs.json | jq -r ".\"${CERT_TYPE}\".crt" #### This will *not* work #####
$ cat certs.json | jq -r ".\"${CERT_TYPE}.crt\""

Upvotes: 0

DukeLion
DukeLion

Reputation: 376

Jq now have better way to access environment variables, you can use env.EMAILID:

projectID=$(cat file.json | jq -r ".resource[] | select(.username==env.EMAILID) | .id")

Upvotes: 14

markroxor
markroxor

Reputation: 6476

Little unrelated but I will still put it here, For other practical purposes shell variables can be used as -

value=10
jq  '."key" = "'"$value"'"' file.json

Upvotes: 47

Zaid
Zaid

Reputation: 688

Posting it here as it might help others. In string it might be necessary to pass the quotes to jq. To do the following with jq:

.items[] | select(.name=="string")

in bash you could do

EMAILID=$1
projectID=$(cat file.json | jq -r '.resource[] | select(.username=='\"$EMAILID\"') | .id')

essentially escaping the quotes and passing it on to jq

Upvotes: 29

Rodrigo Andrade
Rodrigo Andrade

Reputation: 449

I know is a bit later to reply, sorry. But that works for me.

export K8S_public_load_balancer_url="$(kubectl get services -n ${TENANT}-production -o wide | grep "ingress-nginx-internal$" | awk '{print $4}')"

And now I am able to fetch and pass the content of the variable to jq

export TF_VAR_public_load_balancer_url="$(aws elbv2 describe-load-balancers --region eu-west-1 | jq -r '.LoadBalancers[] | select (.DNSName == "'$K8S_public_load_balancer_url'") | .LoadBalancerArn')"

In my case I needed to use double quote and quote to access the variable value.

Cheers.

Upvotes: 4

Andrew Lockhart
Andrew Lockhart

Reputation: 174

Another way to accomplish this is with the jq "--arg" flag. Using the original example:

#!/bin/sh

#this works ***
projectID=$(cat file.json | jq -r '.resource[] | 
select(.username=="[email protected]") | .id')
echo "$projectID"

[email protected]

# Use --arg to pass the variable to jq. This should work:
projectID=$(cat file.json | jq --arg EMAILID $EMAILID -r '.resource[] 
| select(.username=="$EMAILID") | .id')
echo "$projectID"

See here, which is where I found this solution: https://github.com/stedolan/jq/issues/626

Upvotes: 8

asidd
asidd

Reputation: 3291

I resolved this issue by escaping the inner double quotes

projectID=$(cat file.json | jq -r ".resource[] | select(.username==\"$EMAILID\") | .id")

Upvotes: 56

Related Questions