Разобрать JSON членов объекта в Bash переменные - PullRequest
0 голосов
/ 03 апреля 2020

Предположим, у меня установлен этот пакет jq. Итак, я запустил эту команду

curl -s ipinfo.io/33.62.137.111

и получил этот результат

{
  "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"
}

Я знаю, что могу получить city, выполнив это

curl -s ipinfo.io/33.62.137.111 | jq -r '.city' 

Я знаю, что я можно получить region, выполнив это

curl -s ipinfo.io/33.62.137.111 | jq -r '. region' 

Я пытаюсь свернуться 7 раз, чтобы создать 7 переменных.

Есть ли способ создать несколько переменных на основе первого ответа завитка

1 Ответ

4 голосов
/ 03 апреля 2020

Это просто с Bash 4+, используя ассоциативный массив:

#!/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

Пример вывода:

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

Для более старых Bash это немного сложнее, но здесь это

Он разделяет значения по ASCII ETX (значение 3 для E nd из T e x t) и генерирует поток полей с jq, затем считывает каждую переменную в предсказуемом порядке. Если в объекте ответа JSON отсутствует ключ, поле будет пустым.

В отличие от метода ассоциативного массива, имена ключей должны быть известны заранее и предоставлены в предсказанном порядке (все это обрабатывается) по длинному jq запросу).

#!/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"

Пример вывода:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...