Reputation: 58652
Let's assume, I have this package jq
installed. So I ran this command
curl -s ipinfo.io/33.62.137.111
and get this result
{
"ip": "33.62.137.111",
"city": "Columbus",
"region": "Ohio",
"country": "US",
"loc": "39.9690,-83.0114",
"postal": "43218",
"timezone": "America/New_York",
"readme": "https://ipinfo.io/missingauth"
}
I know I can get city
by doing this
curl -s ipinfo.io/33.62.137.111 | jq -r '.city'
I know I can get region
by doing this
curl -s ipinfo.io/33.62.137.111 | jq -r '. region'
I'm trying to curl 7 times to create 7 variables.
Is there a way to create multiple variables based on the first curl response?
Upvotes: 0
Views: 363
Reputation: 3423
You might be interested in xidel. You won't need curl
, jq
, or even a Bash-script for your use-case.
Retrieve the JSON:
xidel -s --user-agent=curl "https://ipinfo.io/33.62.137.111" -e '$json'
{
"ip": "33.62.137.111",
"city": "Columbus",
"region": "Ohio",
"country": "US",
"loc": "39.9690,-83.0114",
"postal": "43218",
"timezone": "America/New_York",
"readme": "https://ipinfo.io/missingauth"
}
Parse the JSON, use Xidel's eval()
function to automatically create (internal) variables for every key-value pair, and use Bash's built-in eval
command to convert them to shell variables:
xidel -s --user-agent=curl "https://ipinfo.io/33.62.137.111" -e '$json() ! eval(x"{.}:=$json/{.}")[0]' --output-format=bash
ip='33.62.137.111'
city='Columbus'
region='Ohio'
country='US'
loc='39.9690,-83.0114'
postal='43218'
timezone='America/New_York'
readme='https://ipinfo.io/missingauth'
result=
eval "$(xidel -s --user-agent=curl "https://ipinfo.io/33.62.137.111" -e '$json() ! eval(x"{.}:=$json/{.}")[0]' --output-format=bash)"
printf '%s\n' $ip $city $region $country $loc $postal $timezone $readme
33.62.137.111
Columbus
Ohio
US
39.9690,-83.0114
43218
America/New_York
https://ipinfo.io/missingauth
Upvotes: 1
Reputation: 19555
It is easy with Bash 4+ using an associative array:
#!/usr/bin/env bash
# Map the JSON response into an associative array
declare -A "assoc_array=($(
curl -s ipinfo.io/33.62.137.111 |
jq -r 'to_entries[] | "[\(.key | @sh)]=\(.value | @sh)"'
))"
IFS=, read -r assoc_array[lat] assoc_array[long] <<<"${assoc_array[loc]}"
echo "Here is how assoc_array was declared/created"
echo
typeset -p assoc_array
echo
echo
# Display the content of the associative array
echo "Here is a breakdown of all entries in the assoc_array:"
echo
for k in "${!assoc_array[@]}"; do
printf '%q = %q\n' "$k" "${assoc_array[$k]}"
done
Sample output:
Here is how assoc_array was declared/created
declare -A assoc_array=([country]="US" [region]="Ohio" [city]="Columbus" [timezone]="America/New_York" [ip]="33.62.137.111" [lat]="39.9690" [readme]="https://ipinfo.io/missingauth" [long]="-83.0114" [loc]="39.9690,-83.0114" [postal]="43218" )
Here is a breakdown of all entries in the assoc_array:
country = US
region = Ohio
city = Columbus
timezone = America/New_York
ip = 33.62.137.111
lat = 39.9690
readme = https://ipinfo.io/missingauth
long = -83.0114
loc = 39.9690\,-83.0114
postal = 43218
It separates values by the ASCII ETX (Value 3
for End of Text) and generates a stream of fields with jq
, then read each variable into the predictable order. If a key is missing from the JSON response object, the field will be empty.
Contrarily to the associative array method, key names have to be known beforehand and provided in a predicted order (all this is handled by the long jq
query).
#!/usr/bin/env bash
IFS=$'\3' read -r ip hostname city region country lat long postal timezone readme < <(
curl -s ipinfo.io/33.62.137.111 |
jq -r '"\(.ip+"\u0003")\(.hostname+"\u0003")\(.city+"\u0003")\(.region+"\u0003")\(.country+"\u0003")\(.loc | split(",") |"\(.[0]+"\u0003")\(.[1]+"\u0003")")\(.postal+"\u0003")\(.timezone+"\u0003")\(.readme+"\u0003")"'
)
printf 'ip = %q\n' "$ip"
printf 'hostname = %q\n' "$hostname"
printf 'city = %q\n' "$city"
printf 'region = %q\n' "$region"
printf 'country = %q\n' "$country"
printf 'latitude = %q\n' "$lat"
printf 'longitude = %q\n' "$long"
printf 'postal code = %q\n' "$postal"
printf 'timezone = %q\n' "$timezone"
printf 'readme = %q\n' "$readme"
Sample output:
ip = 33.62.137.111
hostname = ''
city = Columbus
region = Ohio
country = US
latitude = 39.9690
longitude = -83.0114
postal code = 43218
timezone = America/New_York
readme = https://ipinfo.io/missingauth
Upvotes: 4