Linux jq get value

Работа с JSON в bash с помощью jq

jq — это мощный инструмент, позволяющий читать, фильтровать и писать JSON в bash.

Возможно, вы видели или даже писали bash, который выглядит следующим образом:

curl -s 'https://some-random-api.ml/others/joke' \ | python -m json.tool \ | grep '\"joke\"' \ | cut -d ':' -f 2 \ | sed 's/"/\"/g'

Это трудно читать и еще труднее писать. Чтобы добраться до свойства в теле ответа JSON, вам приходится обращаться к 4 различным утилитам! Bash не понимает JSON из коробки, и использование типичных инструментов для работы с текстом, таких как grep, sed или awk, становится затруднительным. К счастью, есть лучший способ с помощью инструмента под названием jq.

jq может упростить приведенный выше bash до следующего:

curl -s "https://some-random-api.ml/others/joke" | jq '.joke'

Это гораздо приятнее . Упрощая работу с JSON в bash, jq открывает множество возможностей автоматизации, для которых в противном случае мне пришлось бы писать что-то на node.js (что не так уж плохо, просто обычно это занимает больше времени).

Почему бы просто не использовать node.js, когда вам нужно работать с JSON?

Иногда node.js является правильным инструментом. Для большинства задач автоматизации я предпочитаю использовать bash, когда это возможно, потому что он быстрее и даже более портативен (я могу поделиться сценарием bash с членами команды, у которых не установлен node.js). На мой взгляд, bash более выразителен и лаконичен для определенных задач, чем node.

Установка jq

jq не является встроенной командой ни в одну среду, поэтому вам придется установить его. Запустите brew install jq на macOS. О том, как установить jq в других средах, читайте на странице справки по установке.

Основы работы с jq

jq работает аналогично sed или awk — как фильтр, в который вы передаете данные и из которого извлекаете значения. Также как sed или awk, он, по сути, имеет свой собственный специфический язык (DSL) для запросов JSON. К счастью, он очень интуитивно понятен (в отличие от awk)

Читайте также:  Linux посмотреть права группы

Получить свойство

Допустим, у нас есть JSON, который выглядит следующим образом:

Чтобы вывести свойство foo, мы используем оператор ., за которым следует имя свойства.

Это выведет 123, как и ожидалось.

Это работает и с вложенностью. Так .a.b.c.d будет перемещаться вниз по свойствам вложенных объектов.

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

# получите URL-адрес текущей астрономической картинки дня (APOD) apod_url=$(curl -s https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY | jq -r '.hdurl') # получить только имя изображения из URL filepath=$(basename "$apod_url") # Теперь получите изображение и сохраните его curl -s -o "$filepath" "$apod_url" # Используйте AppleScript, чтобы установить его в качестве обоев osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$PWD/$filepath\""

Обратите внимание, что если в свойстве есть пробелы или странные символы, вам придется использовать кавычки. Например:

echo '< "Version Number": "1.2.3" >' | jq '. "Version Number"'

Кроме того, убедитесь, что вы всегда оборачиваете селектор jq в одинарные кавычки, иначе bash попытается интерпретировать все символы как ., тогда как мы хотим, чтобы это делал jq.

Итерация

Теперь давайте посмотрим, как работает итерация. Оператор итератора массива или значения объекта, .[], делает это возможным.

Это выведет 1, 2, 3 на отдельных строках.

В массиве объектов вы можете получить доступ к свойству каждого элемента массива следующим образом:

Или для объекта, .[] выведет значение каждой пары ключ/значение:

Обратите внимание, что вы также можете передать индекс в .[], поэтому

Теперь как нам сделать что-то для каждой строки? Точно так же, как в bash вы обрабатываете все, что выводит несколько строк информации: xargs, циклы for, или некоторые команды, просто обрабатывающие несколько элементов ввода, и т.д. Например:

Функции jq

В jq также есть встроенные «функции». Возвращаясь к предыдущему примеру итерации объекта — допустим, мы хотим получить ключи объекта (не значения) в виде массива:

что вернет a b . Обратите внимание, что мы также используем оператор pipe |, который работает в jq так же, как и в bash — он принимает вывод слева и передает его в качестве ввода справа.

Еще одна удобная функция для массивов и объектов — это функция length, которая возвращает свойство длины массива или количество свойств объекта.

Читайте также:  Основные команды linux terminal

Можно поступить еще более причудливо и создавать промежуточные массивы и объекты на лету. Здесь я объединяю ключи объектов dependencies и devDependencies (из файла package.json) в массив, сглаживаю его, а затем получаю длину.

jq -r '[(.dependencies, .devDependencies) | keys] | flatten | length' package.json

Это возвращает количество зависимостей и devDependencies, которые содержит package.json.

Создание объектов

Вы также можете создавать объекты «на лету». Это может быть полезно для изменения формы некоторых JSON. Например:

Давайте теперь используем его по-настоящему

Что если я захочу провести аудит зависимостей в package.json и удалить все, что не используется? Неиспользуемые зависимости замедляют установку npm для всех и просто мешают. Я мог бы вручную проверить использование каждой зависимости (через grep или в IDE), но если у вас много зависимостей, это быстро надоедает, поэтому давайте автоматизируем это.

set -e # функция для поиска зависимостей grep_dep() < # параметры: $1 = строка для поиска, $2 = каталог для поиска в # [1] grep --include="*.js" --exclude-dir="node_modules" -R --color -n "require\(.*$1.*\)" "$2" # если grep возвращает 0 результатов, то код выхода равен 1. Отсутствие результатов означает, что зависимость не используется if [[ $? >0 ]]; then echo echo "** Использование $1 не найдено, рассмотрите возможность удаления. **" echo fi > # [2] export -f grep_dep # [3] jq -r '.dependencies | keys | .[]' package.json | \ # [4] xargs -I '<>' -P 4 -t bash -c "grep_dep '<>' ."

[1] Вот как работают флаги grep:

  • -include и -exclude-dir сужают круг файлов, которые будут искаться.
  • -R означает рекурсивный, указывает на поиск всех совпадающих файлов
  • -color окрашивает вывод
  • -n отображает номера строк

[2] Я должен экспортировать его, чтобы подпрограмма могла его увидеть. Если вы хотите, чтобы xargs вызывал пользовательскую функцию, вам придется вызывать ее в подпрограмме по некоторым причинам.

[3] -r означает «raw-output», то есть без кавычек вокруг значений, что делает его пригодным для обработки в других командах bash. Мы получаем имена зависимостей в виде массива (это эквивалентно Object.keys(require(‘./package.json’).dependencies) в node.js)

[4] Затем мы передаем их в xargs, который обрабатывает настройку grep для каждой строки. Вот как работают все флаги xargs:

  • -t указывает, что нужно передать эхом построенную команду; полезно для отладки
  • -I <> определяет строку замены, куда будет помещена строка зависимости
  • -P 4 определяет параллельность, так что будет выполняться 4 одновременные команды greps
Читайте также:  Kaspersky small office security linux

мы говорим ему запустить подпрограмму bash, в которой будет вызвана наша функция grep_dep с ее аргументами.

В этом скрипте можно сделать еще много чего интересного, чтобы сделать его более надежным, но это основная суть.

jq — это потрясающий инструмент, который упрощает работу с JSON в bash. DSL для фильтрации, запросов и создания JSON намного глубже, чем то, что я описал здесь, так что смотрите https://stedolan.github.io/jq/manual/.

Похожие записи:

Источник

How to extract value from json contained in a variable using jq in bash

I am writing a bash script which has a json value stored in a variable now i want to extract the values in that json using Jq. The code used is.

json_val= code_val= echo"$json_val" | jq '.code' 
json_val= code_val=echo" $json_val " | jq '.code' 

This does not throws any error but the value in code_val is null. If try to do it manually echo <"code":"lyz1To6ZTWClDHSiaeXyxg","redirect_to":"http://example.com/client-redirect-uri?code=lyz1To6ZTWClDHSiaeXyxg">| jq ‘.code’ it throws parse numeric letter error. how can i do it in first case.

2 Answers 2

json_val='' code_val=$(jq -r '.code' 
  • Wrap complete json string in single quotes
  • use of $(. ) for command substitution
  • Use of

PS: If you're getting json text from a curl command and want to store multiple fields in shell variables then use:

read -r code_val redirect_to < <(curl . | jq -r '.code + "\t" + .redirect_to') 

Where . is your curl command.

in this you have put the json response in ''(single quotes) which makes changes it to literal string. I cannot do this coz i am getting the json_val as a curl response after i run the curl command in earlier line and i save the response in that variable. Or please suggest a way to convert the data in variable to string and then pass to jq.

yeah but there are multiple fields which i need to extract and save in two different variable from the same curl response. Can you suggest a way to extract two values and save in two diff variable from the curl json response. That would do my work.

it does work but also throws errors of echoset not defined read -r code_val redirect_to < <(curl 5dba6fe9eddc81001495f72c.mockapi.io/tyk_test/rate_ poc | jq -r '.rate + "\t" + .individual') echo"$code_val" echo"$redirect_to"

Источник

Оцените статью
Adblock
detector