Как разобрать JSON в сценарии оболочки? - PullRequest
0 голосов
/ 28 ноября 2018

Я запускаю команду curl $(curl -i -o - --silent -X GET --cert "${CERT}" --key "${KEY}" "$some_url") и сохраняю ответ в переменной response.$ {response}, как показано ниже

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 34
Connection: keep-alive
Keep-Alive: timeout=5
X-XSS-Protection: 1; 

{"status":"running","details":"0"}

Я хочу проанализировать JSON {"status":"running","details":"0"} и присвоить 'running' и 'details' двум разным переменным, где я могу напечатать оба состояния и детали.Также, если статус равен ошибке, скрипт должен завершиться.Для выполнения задачи я делаю следующее:

status1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.status')
details1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.details')
echo "Status: ${status1}"
echo "Details: ${details1}"
if [[ $status1 == 'error' ]]; then
    exit 1
fi

Вместо того, чтобы дважды анализировать JSON, я хочу сделать это только один раз.Поэтому я хочу объединить следующие строки, но все же назначить статус и детали двум отдельным переменным -

status1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.status')
details1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.details')

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

Сначала прекратите использовать аргумент -i для curl.Это устраняет необходимость в awk (или любой другой последующей обработке заголовка).

Second:

{
  IFS= read -r -d '' status1
  IFS= read -r -d '' details1
} < <(jq -r '.status + "\u0000" + .details + "\u0000"' <<<"$response")

Преимущество использования NUL в качестве разделителяявляется то, что это единственный символ, который не может присутствовать в значении строки в стиле C (то есть, как хранятся значения переменных оболочки).

0 голосов
/ 28 ноября 2018

Как уже предположил Бенджамин, лучший способ - извлечь только json.Решение Poshi является надежным.

Однако, если вы ищете самый компактный способ сделать это, нет необходимости сохранять ответ как переменную, если единственное, что вы собираетесь с ним сделать, это извлечь другиеПеременные из него на разовой основе.Просто сверните трубку прямо в:

curl "whatever" | jq -r '[.status, .details] |@tsv' 

или

curl "whatever" | jq -r '[.status, .details] |join("\t")'

, и вы получите ваши значения за вас.

0 голосов
/ 28 ноября 2018

Вы можете использовать такую ​​конструкцию, как:

read status1 details1 < <(jq -r '.status + " " + .details' <<< "${response}")

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

...