4

I have a JSON file which contains the following (amongst other properties):

{
  "environment": "$USER"
}

I am extracting that value using jq like so:

ENVIRONMENT="$(jq -r '.environment' "properties.json")"

I want the value of ENVIRONMENT to be my username, not the string $USER - is this possible?

7

Option 1: Just read variable by name

bash allows having variables that reference variables, example:

REF='USER'  # or get it from JSON
echo "${!REF}"
# prints current username

So you can write this:

ENVIRONMENT_REF="$(jq -r '.environment' "properties.json")"
ENVIRONMENT="${!ENVIRONMENT_REF}"

JSON contents:

"environment": "USER"

Option 2: Full shell expansion

Other option, maybe better (but definitely NOT secure) is using eval:

ENVIRONMENT="$(eval "echo $(jq -r '.environment' "properties.json")")"

Note that this is not secure and malicious code can be inserted to the JSON file. What malicious code? Let's look into this properties.json file:

{
    "environment": "$(rm some_file)" 
}

The shell will evaluate this code:

echo $(rm some_file)

… and the file named some_file will be deleted. As you can see, depending on the command entered there, you can cause very serious damage.

4
  • Thank you so much! I had come across option 1 but was missing the key part that the value in the JSON file must not have the $ symbol. Thanks for providing two options as well, and so quickly! – Stuart Leyland-Cole Feb 26 at 17:52
  • @StuartLeyland-Cole, if you think this is the correct answer, click the icon on the left side. – jiwopene Feb 26 at 17:53
  • 1
    @jiwopene and my thanks for the edit pointing out that eval is a security risk. It makes me feel better about upvoting :) Note that the system doesn't allow the asker to accept an answer in the first 15 minutes after posting, so Stuart cannot accept yet. – terdon Feb 26 at 17:55
  • @terdon, added example of malicious code. – jiwopene Feb 26 at 17:58
8

jq provides access to its environment via a $ENV object - similar to perl's $ENV hash or awk's ENVIRON associative array. So for example assuming (as suggested by the accepted answer) your properties.json file looks like

{
  "environment": "USER"
}

then you can do

$ environment="$(jq -r '$ENV[.environment]' properties.json)"
$ echo "$environment"
steeldriver

(best to avoid ALLCAPS for your shell variables). If your file looks like

{
  "environment": "$USER"
}

including the shell-expansion $ then you can use the same method after removing the $:

environment="$(jq -r '$ENV[.environment | sub("^\\$";"")]' properties.json)"

Alternatively, you could pipe the result of a simple lookup through the external envsubst command:

$ environment="$(jq -r '.environment' properties.json | envsubst)"
$ echo "$environment"
steeldriver

See for example Replace environment variables in a file with their actual values?

0

One way can be as follows

ENVIRONMENT=$(printenv $(jq -r '.environment' properties.json |
cut -c2-))
0

This is just a slight re-write of one of the other answers.

In a Linux terminal, create a local folder:

$ mkdir -p ~/unix.se/jq/ && cd ~/unix.se/jq/

Create the file properties.json:

$ echo '{"environment":"USER"}'>properties.json && cat properties.json
{"environment":"USER"}

A side note - pretty formatting with jq:

$ jq '.' properties.json
{
  "environment": "USER"
}

Use the value of the JSON key environment, to set a new environment variable and show its contents: 1

$ JQ_USER=$(jq -r '$ENV[.environment]' properties.json) && echo $JQ_USER
tedly

So far so good, but the problem is that I have been lying.(!) - The properties.json file does not look quite as above, as it has a dollar sign in front of USER, like so:

$ echo '{"environment":"$USER"}'>properties.json && cat properties.json
{"environment":"$USER"}

By getting rid of that disturbing dollar sign, for example by substituting the empty string for it, we can get back to the already working solution:

$ JQ_USER=$(jq -r '$ENV[.environment | sub("\\$";"")]' properties.json)
echo $JQ_USER
tedly

1 When I first ran this, I got an error message starting with jq: error: ENV/0 is not defined at <top-level>. It turns out that $ENV[] requires version 1.6 (or later) of jq.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.