Преобразуйте вложенный JSON объектов в массив в массив bash, используя jq

Я делаю что-то в корне неправильное, но просто не понимаю, что, может ли какой-нибудь добрый человек указать на мою ошибку с jq или JSON здесь?

У меня есть следующие дочерние объекты, содержащиеся в массиве «entries»

{
    "profile": {
        "name": "TesterRun1",
        "download": {
            "entries": [{
                    "ENTRY_A": "testserver1_place_com",
                    "store": "A",
                    "type": "direct"
                },
                {
                    "ENTRY_B": "testserver2_anotherplace_com",
                    "store": "B",
                    "type": "bypass"
                },
                {
                    "ENTRY_B": "testserver2_anotherplace_com",
                    "store": "A",
                    "type": "bypass"
                }
            ]
        }
    }
}

Я хочу преобразовать их в массив, доступный bash через функцию jq «to_entries», используя приведенный ниже запрос, но пока ничего!

jq 'to_entries|.[]|.profile.download.entries|select(.store=="A")|.[]'

Здесь видно, что в JQ Play ничего не возвращается — введите здесь описание ссылки

Пожалуйста, помогите мне сохранить рассудок, что я делаю не так?


person Tav    schedule 14.09.2017    source источник
comment
to_entries не делает вещи доступными для bash. Не уверен, откуда вы взяли идею, что это делает.   -  person Charles Duffy    schedule 15.09.2017
comment
Помимо этого, какой фактический результат вы хотите?   -  person Charles Duffy    schedule 15.09.2017


Ответы (2)


to_entries не имеет ничего общего с предоставлением результатов JQ для bash. Вместо этого он берет каждую запись в объекте JSON и создает пару {"key": key, "value": value}.

Это может быть полезным, если вы хотите идентифицировать и извлечь произвольные ключи. Например:

#!/usr/bin/env bash

jq_script='
.profile.download.entries[]
| select(.store == "A")
| to_entries[]
| select(.key != "store")
| select(.key != "type")
| [.key, .value]
| @tsv
'

declare -A array=( )
while IFS=$'\t' read -r key value; do
  array[$key]=$value
done < <(jq -r "$jq_script")

# print array output
declare -p array

...будет при вводе вашего ввода на стандартный ввод (хотя и в одной строке, без изменений пробелов):

declare -A array=([ENTRY_A]="testserver1_place_com"
                  [ENTRY_B]="testserver2_anotherplace_com" )

... что я предполагаю, из-за отсутствия лучшего описания в вопросе, это то, что вы на самом деле хотите.

person Charles Duffy    schedule 14.09.2017
comment
Привет, Чарльз, извиняюсь за то, что не привел пример желаемого результата. Я думаю, что из того, что у вас есть, видно, что записи, которые я хотел извлечь, не требуют помещения в отдельный объект перед циклом с помощью bash. Кажется намного яснее после ночного сна и с таким наглядным примером передачи данных прямо в массив. Это именно то, что мне нужно, спасибо за очень быстрый и четкий ответ. - person Tav; 15.09.2017

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

#!/bin/bash
data='{
  "profile": {
    "name": "TesterRun1",
    "download": {
      "entries": [
        {
          "entry": "testserver1_place_com",
          "store": "A",
          "type": "direct"
        },
        {
          "entry": "testserver2_anotherplace_com",
          "store": "B",
          "type": "bypass"
        },
        {
          "entry": "testserver2_anotherplace_com",
          "store": "A",
          "type": "bypass"
        }
      ]
    }
  }
}'
filter='
        .profile.download.entries[]
      | select(.store == "A")
      | .entry, .store, .type
'      
declare -a ENTRY
declare -a STORE
declare -a TYPE
i=0
while read -r entry; read -r store; read -r type; do
    ENTRY[$i]="$entry"
    STORE[$i]="$store"
    TYPE[$i]="$type"
    i=$((i + 1))
done < <(jq -Mr "$filter" <<< "$data")
declare -p ENTRY STORE TYPE

Выход

declare -a ENTRY='([0]="testserver1_place_com" [1]="testserver2_anotherplace_com")'
declare -a STORE='([0]="A" [1]="A")'
declare -a TYPE='([0]="direct" [1]="bypass")'
person jq170727    schedule 14.09.2017