jq. | Кодементор
Что отличает хорошего разработчика от отличного разработчика?
В то время как хороший разработчик решает конкретную задачу (например, создает новый компонент React, редактирует конечную точку REST и т. д.), у отличного разработчика есть широкое понимание и набор инструментов которые могут помочь ему в различных ситуациях. (мой2с)
Одним из таких инструментов является jq — невероятный CLI инструмент с 13к+ звезд на Github. Вы можете видеть это как Швейцарский армейский нож для работы с JSON. Это очень полезно, когда вы хотите быстро понять данные в JSON; это сэкономило мне много времени за последние годы. Мне нравится использовать его, потому что это инструмент командной строки, и я люблю делать как можно больше работы в CLI. Это мой личный выбор — и другая тема.
посмотрим как jq
могу помочь тебе!
Настраивать
Вы найдете все необходимые инструкции здесь. Все, что вам нужно сделать, это загрузить двоичный файл для используемой вами ОС и переместить его в место, где ОС ищет двоичные файлы, например /usr/local/bin
— для линукс/макОС.
Кроме того, вы можете установить его с помощью менеджера пакетов (подходящего для вашей ОС). В macOS вы можете использовать заваривать
$ brew install jq
и в Ubuntu вы можете использовать
$ sudo apt-get install jq
Спасибо, Тео, за указание на это в разделе комментариев.
Полезные ресурсы: руководство, руководство а также детская площадка. Я настоятельно рекомендую вам посмотреть в руководстве все фильтры jq, используемые в этом посте.
Базовая информация
Как указано в руководство, каждая программа jq является фильтром. Он принимает входные данные (данные JSON) и производит выходные данные. Существует множество встроенных фильтров для извлечения того или иного поля объекта, или преобразования числа в строку, или различных других стандартных задач.
Сегодня мы собираемся изучить некоторые из этих фильтров.
Хватит болтать, давайте посмотрим на примеры
Вы уже видели один, который очень удобен: jq .
краткая форма jq '.'
. Эта команда напечатает весь JSON и украсит его, если он минимизирован.
я использую пародия для создания некоторых фиктивных данных. Здесь вы можете найти JSON, который я использую для тестов.
Давай попробуем jq .
Сначала давайте загрузим файл JSON
$ cd ~
$ curl -s > mock.json
Теперь проверьте вывод этих команд:
$ cat mock.json
$ cat mock.json | jq .
Как было сказано ранее, jq .
напечатает весь JSON, но украсит. Довольно круто, да?
Основная фильтрация: .[].а
Что, если нам нужны только электронные письма этих пользователей? Это проще, чем вы думаете.
Если вы внимательно посмотрите на вывод предыдущей команды, вы заметите, что корень JSON — это массив.
Чтобы получить все элементы этого массива, нет сам массив, вы можете использовать []
. Вы можете думать об этом как разлагающийся массив.
$ cat mock.json | jq .[]
Чтобы получить только электронные письма, просто добавьте .email
поэтому фильтр становится:
$ cat mock.json | jq .[].email
Массивы: индекс, вложенные фильтры
Чтобы получить первый элемент массива, все, что вам нужно сделать, это:
$ cat mock.json | jq .[0]
Конечно, вы можете добавить дополнительные фильтры для получения электронной почты из первого элемента или для получения онлайн-статуса первого устройства, используемого первым человеком:
$ cat mock.json | jq .[0].email
$ cat mock.json | jq .[0].devices[0].online
Примечание: jq .a.b.c
а также jq '.a | .b | .c'
дают тот же результат. Таким образом, мы достигли бы того же результата, если бы использовали:
$ cat mock.json | jq '.[0] | .email'
$ cat mock.json | jq '.[0] | .devices[0] | .online'
Длина: построение массива, длина, труба
Что делать, если вы хотите получить общее количество писем? Вы можете использовать wc -l
конечно.
$ cat mock.json | jq .[].email | wc -l
Но вы также можете использовать length
функция в jq. Давайте посмотрим на это в действии!
$ cat mock.json | jq '.[].email | length'
Не то, что вы ожидали, верно? На самом деле это длина строк, потому что length
применяется ко всем значениям электронной почты (разложенный массив); length
работает с массивами, строками и объектами. Так, например, делая jq '.[] | length'
даст количество полей в каждом объекте.
Чтобы получить количество писем, все, что нам нужно сделать, это создать массив, что интуитивно понятно.
$ cat mock.json | jq '[.[].email] | length'
Вы можете спросить себя, что произойдет, если вы позвоните jq '. | length'
. Это даст вам общее количество элементов в массиве, потому что он не был разрушен/разложен.
Фильтр: выбрать и, содержит, ==
Что, если вы хотите отфильтровать эти электронные письма? Вы можете использовать grep
конечно.
$ cat mock.json | jq .[].email | grep @google
Но вы также можете использовать select
.
$ cat mock.json | jq '.[].email | select(. | contains("@google"))'
Давайте добавим еще одно условие в наш фильтр, чтобы получить всех женщин с электронной почтой Google.
$ cat mock.json | jq '.[] | select((.email | contains("@google")) and .gender == "Female")'
Этот фильтр вернет 2 объекта (не электронные письма), потому что первый фильтр .[]
возвращает объекты, которые мы фильтруем с помощью select((.email | contains("@google")) and .gender == "Female")
. Если мы внимательно посмотрим на этот бит, мы увидим 2 условия .gender == "Female"
а также (.email | contains("@google")
. Трубка |
используется для применения обоих select
а также contains
функции.
Примечание: Мы использовали конвейеры внутри команды jq для объединения фильтров и вызова length
а также select
. Помните об одинарных кавычках, используемых для инкапсуляции всех фильтров.
Если мы хотим получить только электронную почту, все, что нам нужно сделать, это подключить еще один фильтр.
$ cat mock.json | jq '.[] | select((.email | contains("@google")) and .gender == "Female") | .email'
Длина + Фильтр
Давайте узнаем, сколько женщин используют электронную почту Google. Нам нужно только построить массив и вызвать length
.
$ cat mock.json | jq '[.[] | select((.email | contains("@google")) and .gender == "Female")] | length'
Нравится пока?
Построение объекта и интерполяция строк: {}, (.a)
Допустим, мы хотим иметь массив объектов, содержащий только 3 поля: first_name
, last_name
а также email
. Нам нужно создать несколько новых объектов, и, опять же, синтаксис интуитивно понятен.
$ cat mock.json | jq '.[] | {first_name: .first_name, last_name: .last_name, email: .email}'
Как насчет конкатенации first_name
а также last_name
? Решением является интерполяция строк, аналогичная синтаксису JS.
$ cat mock.json | jq '.[] | {name: "\(.first_name) \(.last_name)", email: .email}'
Группировка: group_by
Еще одна крутая вещь, которую может сделать jq, — это группировка. Мы можем продемонстрировать это, сгруппировав по полу.
$ cat mock.json | jq group_by(.gender)
Это сработало, но результат не очень читабелен — это массив, который содержит 2 других массива, содержащих сгруппированные объекты. Давайте немного подкорректируем. Мы разложим 2 раза (так как у нас есть массив в массиве).
$ cat mock.json | jq 'group_by(.gender) | .[] | .[]'
И мы сформируем несколько новых объектов, используя технику, представленную выше.
$ cat mock.json | jq 'group_by(.gender) | .[] | .[] | {name: "\(.first_name) \(.last_name)", gender: .gender}'
Выглядит хорошо, но вещи все вместе. Мы хотим сохранить 2 разных массива с. Метод построения массива — наше решение.
$ cat mock.json | jq 'group_by(.gender) | .[] | [.[] | {name: "\(.first_name) \(.last_name)", gender: .gender}]'
Последняя вещь. Давайте посмотрим, сколько мужчин и сколько женщин в нашем наборе данных.
$ cat mock.json | jq 'group_by(.gender) | .[] | [.[] | {name: "\(.first_name) \(.last_name)", gender: .gender}] | length'
Выводы
jq — очень мощный и легкий инструмент, и я думаю, что каждый разработчик должен иметь хотя бы базовое представление о том, как он работает.
Я только поцарапал поверхность, и я настоятельно рекомендую взглянуть на руководство и посмотреть, на что он способен.
Спасибо
Спасибо за чтение! Я надеюсь, это поможет.
Код включен!