возвращать определенные элементы в объекте json, используя bash - PullRequest
0 голосов
/ 01 июня 2018

Я пытаюсь получить ответ json (из команды curl и jq, установленной на моем Linux-компе) с несколькими объектами и редактировать каждый с помощью цикла for.Проблема в том, что я не понимаю, как взять каждый {} и преобразовать их в отдельные объекты.Например, мой ответ json:

{
  "Name": "testuser1",
  "Username": "testuser1",
  "Url": "www.test1.com"
}
{
  "Name": "testuser2",
  "Username": "testuser2",
  "Url": "www.test2.com"
}

В идеале, я хочу сослаться на каждого по номеру.Например, "echo $ item | jq '.Name [0]'" для

{
  "Name": "testuser1",
  "Username": "testuser1",
  "Url": "www.test1.com"
}

Когда я запускаю команду, указанную выше, я получаю следующую ошибку.

jq: error (at <stdin>:1): Cannot index string with number

Я быхотел бы запустить forloop для каждого объекта.

Ответы [ 3 ]

0 голосов
/ 01 июня 2018

Чтобы выбрать только имя, необходимо выполнить индексирование до , пытаясь перейти к элементу Name:

jq -rs '.[0].Name'

В отличие от этого, для циклаwhile read подход , данный ответом @ chepner действительно уместен.

0 голосов
/ 02 июня 2018

jq ориентирован на поток, поэтому, если вы хотите выполнить какую-то операцию с каждым объектом, тогда может быть достаточно определить эту операцию в jq и позволить jq обрабатывать поток без лишних слов.

Еслипо какой-то причине вам нужен индекс каждого элемента в потоке, тогда вы можете избежать опции -s, если ваш jq имеет inputs (как и jq 1.5).(Отказ от опции -s экономит память.)

В следующем предполагается, что ваш jq имеет inputs;эта индексация основана на 0;и что jq вызывается с опцией -n.

Генерация индекса

foreach inputs as $input (-1; .+1; [., $input])

Это создаст поток массивов [INDEX, ITEM].Затем вы можете использовать дополнительные фильтры jq, используя оператор канала jq (|).

Выбор i-го элемента из потока JSON-сущностей.

Для иллюстрации подходящегометод для вызова jq, предположим, что поток сущностей JSON происходит из curl COMMAND, и нам нужен второй элемент (то есть с индексом 1).

Invocation

curl COMMAND | jq --argjson i 1 -n -f program.jq

(Обратите внимание на параметр командной строки -n!)

program.jq

def get($i):
  label $done
  | foreach inputs as $input (-1; .+1;
      if $i == . then $input, break $done else empty end);

get($i)
0 голосов
/ 01 июня 2018

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

$ jq -sr '.[].Name' tmp.json
testuser1
testuser2

Если вы хотите сослаться на определенный элемент потока, вы можете:

$ jq -sr '.[1].Name' tmp.json
testuser2

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

while IFS= read -r name; do
    ...
done < <(jq -sr '.[].Name' tmp.json)
...