Фильтрация JSON-запросов с помощью JQ и bash-скриптов

Фильтрация JSON-запросов с помощью JQ и bash-скриптов

Я запрашиваю JSON из Twitch со следующими данными: curl --silent -H 'Accept: application/vnd.twitchtv.v3+json' -X GET https://api.twitch.tv/kraken/streams/$1где $1находятся входные данные, которые я отправляю для своей функции.

Теперь моя цель — отфильтровать JSON, передав это после curl: | jq '.stream.channel.something' Я пытаюсь получить 3 разных строковых значения с помощью фильтрации jq. Мне удается довести их до этого уровня:

{
    "first": "lor"
    "second": "em"
    "third": "ipsum"
}

Как с ними работать внутри кода?


Альтернативы, которые я придумал, следующие:

  1. Создайте вывод curl, отфильтруйте его, а затем удалите.
  2. Отправьте 3 запроса cURL -- (бесполезный пожиратель производительности?).

решение1

Как я уже сказал, я не очень разбираюсь в json или jq, но мне не удалось заставить jq проанализировать ваш пример вывода:

{
    "first": "lor"
    "second": "em"
    "third": "ipsum"
}

parse error: Expected separator between values at line 3, column 12

Поэтому я превратил входные данные в:

{
  "stream" : {
    "channel" : {
      "something" : {
        "first": "lor",
        "second": "em",
        "third": "ipsum"
      }
    }
  }
}

... на основе того, что я понял из вашего вызова jq. Надеюсь, это похоже на то, что выводит команда curl.

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

# this is just your original curl command, wrapped in command substitution,
# in order to assign it to a variable named 'output':
output=$(curl --silent -H 'Accept: application/vnd.twitchtv.v3+json' -X GET https://api.twitch.tv/kraken/streams/$1)

# these three lines take the output stream from above and pipe it to
# separate jq calls to extract the values; I added some pretty-printing whitespace
first=$( echo "$output" | jq '.["stream"]["channel"]["something"]["first"]' )
second=$(echo "$output" | jq '.["stream"]["channel"]["something"]["second"]')
third=$( echo "$output" | jq '.["stream"]["channel"]["something"]["third"]' )

С результатами:

$ echo $first
"lor"
$ echo $second
"em"
$ echo $third
"ipsum"

решение2

Предположим, что ваш файл является допустимым JSON (а данные в вопросе таковыми не являются):

{
  "first": "lor",
  "second": "em",
  "third": "ipsum"
}

Вы можете использовать jqэто для создания трех присваиваний, которые можно безопасно оценить в оболочке:

eval "$(
    jq -r '
        @sh "first=\(.first)",
        @sh "second=\(.second)",
        @sh "third=\(.third)"' file.json
)"

Оператор @shin jqвыведет назначения на форму first='lor', которую оболочка сможет оценить.

Для bashоболочки вы также можете создать массив назначений:

eval "$(
    jq -r '@sh "array=(\([.first, .second, .third]))"' file.json
)"

Здесь jqкоманда сгенерирует что-то вроде array=('lor' 'em' 'ipsum'), что при вычислении bashсоздаст массив arrayс указанным содержимым.

Вы можете использовать этот jqоператор @sh "array=(\([.[]]))"для создания массива значений всех ключей, предполагая, что каждое значение является скаляром.

Связанный контент