4

I'm curling an endpoint:

#!/bin/bash
instance_info=$(curl -sk https://internal.admin.com/app/instance)

which gives a json response:

{
"basePath": "/install", 
"metadata": {
    "deployed_artifact": "app01", 
    "docker": "True",  
    "http_port": "7471",
    "url": "www.google.com"
}, 
"name": "app-01", 
"server": "webserver1"
}

I'm trying to avoid curling more than once to get the variables I need from the json using JQ.

Using bash I'd really appreciate if someone can show me how to store the response as another var and then use this to variablize name: server: url: http_port:

The following seems to run the curl twice:

#!/bin/bash
instance_info=$(curl -sk https://internal.admin.com/app/instance)

server_name=$(echo instance_info | /usr/bin/jq --raw-output '.server')
url=$(echo instance_info | /usr/bin/jq --raw-output '.url')
3
  • 1
    No, your example runs curl only once. Commented Apr 27, 2016 at 10:59
  • I don't see why the curl line would be executed twice. How do you tell it is executed twice? Commented Apr 27, 2016 at 10:59
  • And you can get rid of the echo using /usr/bin/jq <args> <<< "$instance_info". Commented Apr 27, 2016 at 11:05

4 Answers 4

4

You are calling curl once and this suffices. Then you have the content in a variable, so you can access it without calling curl again.

Regarding your code, your approach is fine but you are missing $ when you are echoing the variable:

server_name=$(echo $instance_info | /usr/bin/jq --raw-output '.server')
#                  ^

See a sample. Here I hardcode the JSON:

your_json='
{
"basePath": "/install", 
"metadata": {
    "deployed_artifact": "app01", 
    "docker": "True",  
    "http_port": "7471",
    "url": "www.google.com"
}, 
"name": "app-01", 
"server": "webserver1"
}'

for the server:

$ echo "$your_json" | jq --raw-output '.server'
webserver1

For the url you need to indicate the block where it lies on. That is, metadata:

$ echo "$your_json" | jq --raw-output '.metadata.url'
www.google.com

To store into a variable, say:

your_field=$(echo "$your_json" | jq --raw-output 'XXXX')
#                                                 ^^^^
Sign up to request clarification or add additional context in comments.

Comments

2

Here is a script which demonstrates how to use jq's @sh formatting directive along with bash eval to set bash variables using the output of a filter. In this case we hardcode the json which presumably would have come from curl.

#!/bin/bash
instance_info='
{
"basePath": "/install", 
"metadata": {
    "deployed_artifact": "app01", 
    "docker": "True",  
    "http_port": "7471",
    "url": "www.google.com"
}, 
"name": "app-01", 
"server": "webserver1"
}'

eval "$(jq -M -r '@sh "server_name=\(.server) url=\(.metadata.url)"' <<< "$instance_info")"

echo $server_name
echo $url

When run this produces the output

webserver1
www.google.com

The Extract data and set shell variables section of the JQ Cookbook has more examples of @sh.

Comments

1
sed -rn 's/[ ]*"([^"]*)"[^"]*("[^"]*").*/\1=\2/gp'' file.json

O/P:

basePath="/install"
deployed_artifact="app01"
docker="True"
http_port="7471"
url="www.google.com"
name="app-01"
server="webserver1"

eval this output you can get the variable

eval $(sed -rn 's/[ ]*"([^"]*)"[^"]*("[^"]*").*/\1=\2/gp' file.json )
echo $name $server

O/p:

app-01 webserver1

Comments

0

Read the values with one jq pass then there's no need to store the json:

read name server url http_port < <(
    curl -sk https://internal.admin.com/app/instance | \
    jq --raw-output '[.name, .server, .metadata.url, .metadata.http_port] | join(" ")'
)

echo -e "\$name: $name\n\$server: $server\n\$url: $url\n\$http_port $http_port"
$name: app-01
$server: webserver1
$url: www.google.com
$http_port 7471

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.