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

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

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

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

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

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

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

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

Установка jq

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

Debian\Ubuntu

Fedora\CentOS

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

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

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

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

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

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

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

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

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

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

Итерация

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

Вот очень простой пример:

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

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

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

Это вернет значение 1 2.

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

вернет только bar.

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

Функции jq

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

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

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

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

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

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

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

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

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

[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

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

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

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

Понравилась статья? Поделиться с друзьями:
Добавить комментарий