Skip to content
Назад к блогу
Руководства

Шпаргалка по jq: 30 реальных паттернов для JSON в командной строке

Освойте jq на 30 проверенных паттернах для фильтрации, преобразования и извлечения JSON в командной строке — от kubectl и AWS до лог-файлов.

12 мин чтения

Шпаргалка по jq: 30 реальных паттернов для JSON в командной строке

Вы пайпите kubectl get pods -o json в less, и терминал замирает на двухмегабайтной стене JSON. А вам нужно лишь имя каждого пода в фазе Running. jq сделает это в трёх символах синтаксиса фильтра — стоит только знать словарь.

Это не справочник по синтаксису. Это 30 паттернов, которые вы реально будете печатать, сгруппированных по задаче: доступ, фильтрация, преобразование, агрегация, форматирование и склейка с реальными утилитами вроде kubectl, aws и docker.

Когда использовать jq, а когда форматтер в браузере или код

jq не всегда правильный ответ. Три честных варианта выбора:

СитуацияЛучший инструментПочему
Один ответ API, нужны подсветка и номера строк ошибокФорматировщик JSON в браузереВизуальный diff, ноль настройки, приватность в браузере
Shell-пайплайн, обработка логов, CI-скрипт, удалённый серверjqКомпозиция, скриптуемость, без зависимости от GUI
Бизнес-логика, юнит-тесты, сложные ветвленияКод на языке (JS / Python)Реальный отладчик, типы, библиотеки

Выбирайте jq, когда задача живёт в shell-пайплайне — всё остальное обычно легче решать другим инструментом.

Установка и первый пайплайн

jq — это один бинарь на каждой крупной платформе:

# macOS
brew install jq

# Debian / Ubuntu
sudo apt install jq

# Windows (winget)
winget install jqlang.jq

Первый пайплайн с identity-фильтром:

curl -s https://api.github.com/users/octocat | jq .

Фильтр . принимает вход и без изменений выводит pretty-printed. Уже это заменяет большинство моментов «дайте я открою этот JSON в редакторе».

Пять флагов покрывают 90% реальной работы:

ФлагНазначение
-rRaw output — убирает кавычки вокруг строкового результата
-cCompact — одно JSON-значение на строку (NDJSON)
-sSlurp — читает все входы в один массив
-RRaw input — читает строки как строки, а не как JSON
-nNull input — не читает stdin, использует null как вход

Базовая ментальная модель: фильтры и пайпы

Фильтр принимает одно JSON-значение на вход и выдаёт ноль или больше JSON-значений на выходе. Фильтры собираются через пайп |, который посылает каждый выход левого фильтра как вход правому. Та же ментальная модель, что и shell-пайпы, только вместо байтов текут JSON-значения.

# . — identity
echo '{"name":"Alice"}' | jq '.'

# .key — доступ к полю
echo '{"name":"Alice"}' | jq '.name'

# .key.sub — глубокий путь
echo '{"user":{"email":"a@x.com"}}' | jq '.user.email'

# .[] — итерация по элементам массива (несколько выходов)
echo '[{"id":1},{"id":2}]' | jq '.[] | .id'

# Композиция через пайп: каждый выход .items[] идёт в .name
echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq '.items[] | .name'

Это вся грамматика. 30 паттернов ниже — комбинации этих примитивов.

30 паттернов, которыми вы реально будете пользоваться

Каждый паттерн показывает входной JSON, команду и выход. Любой можно скопировать в свой терминал.

Доступ и извлечение (паттерны 1-5)

Паттерн 1 — Безопасный доступ через ?

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

echo '{"name":"Alice"}' | jq '.address?.city?'
# Output: null

? подавляет ошибки на отсутствующих ключах. Без него .address.city бросил бы ошибку типа, если .address отсутствует.

Паттерн 2 — Доступ по глубокому пути

echo '{"user":{"profile":{"email":"a@x.com"}}}' | jq '.user.profile.email'
# Output: "a@x.com"

Паттерн 3 — Срез массива

echo '[10,20,30,40,50]' | jq '.[1:3]'
# Output: [20, 30]

echo '[10,20,30,40,50]' | jq '.[-1]'
# Output: 50

Отрицательные индексы считаются с конца. Срезы используют полуоткрытые интервалы, как в Python.

Паттерн 4 — Рекурсивный обход для поиска каждого совпадающего ключа

echo '{"a":{"name":"x"},"b":[{"name":"y"},{"id":1}]}' | jq '.. | .name? | select(. != null)'
# Output: "x"
#         "y"

.. обходит каждое значение в дереве. В сочетании с .name? и select извлекает все поля name независимо от глубины — незаменимо при изучении незнакомых JSON-схем.

Паттерн 5 — Перечислить все ключи объекта

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys'
# Output: ["apple", "mango", "zebra"]

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys_unsorted'
# Output: ["zebra", "apple", "mango"]

keys сортирует по алфавиту; keys_unsorted сохраняет порядок вставки.

Фильтрация (паттерны 6-10)

Паттерн 6 — Фильтрация массива по условию

echo '[{"age":20},{"age":30},{"age":40}]' | jq 'map(select(.age > 25))'
# Output: [{"age":30},{"age":40}]

map(f) применяет f к каждому элементу; select(cond) оставляет элементы, где условие выполняется.

Паттерн 7 — Совпадение по префиксу строки

echo '[{"name":"api-gateway"},{"name":"web-ui"},{"name":"api-auth"}]' \
  | jq '.[] | select(.name | startswith("api"))'
# Output: {"name":"api-gateway"}
#         {"name":"api-auth"}

Полезны также: endswith("..."), contains("..."), test("^regex$").

Паттерн 8 — Комбинированные условия

echo '[{"type":"A","count":5},{"type":"A","count":15},{"type":"B","count":20}]' \
  | jq '.[] | select(.type == "A" and .count > 10)'
# Output: {"type":"A","count":15}

and, or, not работают как ожидается.

Паттерн 9 — Удаление чувствительных полей

echo '{"user":"alice","password":"s3cret","token":"abc"}' | jq 'del(.password, .token)'
# Output: {"user":"alice"}

del() принимает несколько путей и безопасен, если какой-то из них отсутствует.

Паттерн 10 — Дедупликация по полю

echo '[{"id":1,"v":"a"},{"id":2,"v":"b"},{"id":1,"v":"a2"}]' | jq 'unique_by(.id)'
# Output: [{"id":1,"v":"a"},{"id":2,"v":"b"}]

unique дедуплицирует целые значения; unique_by(f) — по результату фильтра.

Преобразование (паттерны 11-15)

Паттерн 11 — Переименование полей

echo '[{"first_name":"Alice","age":30}]' | jq 'map({name: .first_name, age})'
# Output: [{"name":"Alice","age":30}]

Сокращение {age} эквивалентно {age: .age}.

Паттерн 12 — Добавление вычисляемого поля со строковой интерполяцией

echo '[{"first":"Alice","last":"Chen"}]' \
  | jq 'map(. + {fullName: "\(.first) \(.last)"})'
# Output: [{"first":"Alice","last":"Chen","fullName":"Alice Chen"}]

\(expr) вычисляет expr и подставляет его значение в строку.

Паттерн 13 — Развёртывание вложенных массивов

echo '[{"tags":["a","b"]},{"tags":["c"]}]' | jq '[.[] | .tags[]]'
# Output: ["a","b","c"]

echo '[[1,2],[3,[4,5]]]' | jq 'flatten'
# Output: [1,2,3,4,5]

flatten принимает необязательный аргумент глубины: flatten(1) снимает только один уровень.

Паттерн 14 — Объект в массив и обратно

echo '{"a":1,"b":2}' | jq 'to_entries'
# Output: [{"key":"a","value":1},{"key":"b","value":2}]

echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# Output: {"a":1,"b":2}

Эта пара позволяет преобразования, требующие итерации по ключам объекта, — то, что нельзя сделать напрямую через dot-path.

Паттерн 15 — Глубокий merge двух объектов

echo '{"a":{"x":1},"b":2}' | jq '. * {a:{y:9}, c:3}'
# Output: {"a":{"x":1,"y":9},"b":2,"c":3}

Оператор * делает глубокий merge. Для поверхностного — + (правый аргумент побеждает).

Агрегация (паттерны 16-20)

Паттерн 16 — Длина массивов, объектов и строк

echo '[1,2,3,4]' | jq 'length'      # 4
echo '{"a":1,"b":2}' | jq 'length'  # 2
echo '"hello"' | jq 'length'        # 5

Паттерн 17 — Сумма поля

echo '[{"price":10},{"price":25},{"price":5}]' | jq '[.[].price] | add'
# Output: 40

add суммирует числа, конкатенирует строки или сливает массивы — в зависимости от типа входа.

Паттерн 18 — Группировка по полю

echo '[{"cat":"A","n":1},{"cat":"B","n":2},{"cat":"A","n":3}]' | jq 'group_by(.cat)'
# Output: [[{"cat":"A","n":1},{"cat":"A","n":3}],[{"cat":"B","n":2}]]

Каждая группа становится внутренним массивом. Сочетайте с map, чтобы агрегировать по группам.

Паттерн 19 — Сортировка по убыванию

echo '[{"date":"2026-01-03"},{"date":"2026-01-01"},{"date":"2026-01-02"}]' \
  | jq 'sort_by(.date) | reverse'
# Output: [{"date":"2026-01-03"},{"date":"2026-01-02"},{"date":"2026-01-01"}]

Строки дат в ISO 8601 сортируются корректно как строки. Для других форматов сначала разберите дату — руководство по Unix timestamp подробно разбирает секунды эпохи, миллисекунды и преобразование часовых поясов.

Паттерн 20 — Максимум или минимум по полю

echo '[{"name":"a","rating":4.1},{"name":"b","rating":4.8},{"name":"c","rating":3.9}]' \
  | jq 'max_by(.rating)'
# Output: {"name":"b","rating":4.8}

min_by, max_by возвращают один элемент. Для топ-N: sort_by(.rating) | reverse | .[:N].

Форматирование вывода (паттерны 21-25)

Паттерн 21 — Вывод в CSV

echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' \
  | jq -r '.[] | [.name, .age] | @csv'
# Output: "Alice",30
#         "Bob",25

@csv оборачивает строки в кавычки и экранирует кавычки внутри. -r снимает внешние JSON-кавычки строки, поэтому CSV сразу пайпится дальше. Полный round-trip между CSV и JSON в пайплайне разобран в руководстве по конвертации CSV ↔ JSON.

Паттерн 22 — Вывод в TSV

echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' \
  | jq -r '.[] | [.id, .name] | @tsv'
# Output: 1	Alice
#         2	Bob

Tab-separated вывод хорошо дружит с cut, awk и column -t.

Паттерн 23 — Сырой вывод строк

echo '["alpha","beta"]' | jq -r '.[]'
# Output: alpha
#         beta

Без -r каждая строка была бы в кавычках. Сырой вывод — это то, что вы кормите xargs, while read или другой shell-команде.

Паттерн 24 — NDJSON / JSON Lines

echo '[{"a":1},{"a":2}]' | jq -c '.[]'
# Output: {"a":1}
#         {"a":2}

Каждая строка — самостоятельное JSON-значение. Это формат, который применяют Kafka, Elasticsearch и большинство структурированных логгеров. -c также убирает все внутренние пробелы.

Паттерн 25 — Строковая интерполяция для форматированного вывода

echo '[{"name":"server-1","cpu":0.73},{"name":"server-2","cpu":0.21}]' \
  | jq -r '.[] | "\(.name): \(.cpu * 100)% CPU"'
# Output: server-1: 73% CPU
#         server-2: 21% CPU

Отлично подходит для сводок и log-строк, где сырой JSON был бы шумом.

DevOps в реальной жизни (паттерны 26-30)

Паттерн 26 — kubectl: имена всех запущенных подов

kubectl get pods -o json \
  | jq -r '.items[] | select(.status.phase=="Running") | .metadata.name'

Пайплайн: итерация по подам, оставляем только Running, выдаём имя как сырую строку.

Паттерн 27 — AWS EC2: ID инстансов с публичными IP

aws ec2 describe-instances \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, .PublicIpAddress // "none"] | @tsv'

Альтернативный оператор // подставляет fallback, когда поле null — в столбце вывода не будет буквального null.

Паттерн 28 — GitHub API: объединение пагинированных результатов

for p in 1 2 3; do
  curl -s "https://api.github.com/orgs/myorg/repos?per_page=100&page=$p"
done | jq -s 'add | map(.name)'

-s slurp-ит все ответы в один array-of-arrays, add склеивает их, далее map(.name) извлекает имена. Типовой паттерн для любого пагинированного API.

Паттерн 29 — Фильтрация структурированных лог-файлов

cat app.log | jq -c 'select(.level=="error")'

Предполагается, что лог в NDJSON (один JSON-объект на строку). Сочетайте с tail -f для живого мониторинга:

tail -f app.log | jq -c 'select(.level=="error") | {ts: .timestamp, msg: .message}'

Паттерн 30 — Docker: все используемые имена образов

docker inspect $(docker ps -q) | jq -r '.[].Config.Image' | sort -u

Хорошо подходит для быстрой проверки, какие версии образов запущены на хосте.

Распространённые ошибки и как их исправить

В эти ошибки упирается каждый пользователь jq. Знание исправления заранее экономит часы.

Cannot iterate over null (null)

Поле, по которому вы пытались итерировать, оказалось null или отсутствует. Два исправления:

# Вариант A: optional-оператор
echo '{}' | jq '.items[]?'
# Output: (ничего, без ошибки)

# Вариант B: альтернативный оператор со значением по умолчанию
echo '{}' | jq '(.items // [])[]'
# Output: (ничего, без ошибки)

Используйте ?, когда нужно тихо пропустить. Используйте // [], когда нужно навязать конкретный пустой массив, чтобы дальнейшие фильтры всё-таки отработали.

Cannot index array with "key"

Вы написали .foo, но текущее значение — массив. Добавьте [], чтобы итерировать:

# Неверно
echo '{"users":[{"name":"Alice"}]}' | jq '.users.name'
# Error: Cannot index array with "name"

# Верно
echo '{"users":[{"name":"Alice"}]}' | jq '.users[].name'
# Output: "Alice"

Проблемы с экранированием в shell

Используйте одинарные кавычки вокруг всей программы jq, двойные — внутри для строковых литералов:

# Работает везде
jq '.users[] | select(.role == "admin")'

# Ломается — двойные кавычки сначала интерпретирует shell
jq ".users[] | select(.role == \"admin\")"

Особенности Windows PowerShell

PowerShell обращается с одинарными кавычками иначе. Лучше используйте двойные кавычки вокруг программы и экранируйте внутренние, либо применяйте here-string:

jq "@'
.users[] | select(.role == \"admin\")
'@"

Для чего-то нетривиального сохраните фильтр в .jq-файл и запускайте jq -f filter.jq.

Неправильное использование raw output

-r влияет только на строковые результаты. Если подать ему объект — получится обычный JSON-объект:

echo '{"a":1}' | jq -r '.'
# Output: {"a":1}     ← без изменений; -r нечего было снимать

Если хотите конкретное поле без кавычек — выберите его сначала: jq -r '.a'.

jq отвергает JSON с комментариями или замыкающими запятыми

echo '{"a": 1, /* note */ "b": 2,}' | jq .
# parse error: Invalid numeric literal

jq следует строгому RFC 8259 JSON — без комментариев, без замыкающих запятых, без неэкранированных ключей. Если файл — JSON5 или JSONC (часто в конфигах), сначала уберите расширения. Руководство по форматированию JSON5 и JSONC разбирает, какие парсеры с ними работают и как привести к строгому JSON перед подачей в jq.

jq и альтернативы: gron, fx, jj, yq

jq — не единственный вариант, и иногда другой инструмент быстрее:

ИнструментСильная сторонаКогда тянуться к нему
gronРазворачивает JSON в grep-абельные путиИзучение незнакомых схем — когда не знаете, где ключ
fxИнтерактивный TUI-обозреватель с подсветкойПросмотр большого JSON вручную
jjНамного быстрее jq, ограниченный синтаксисГорячие циклы по миллионам записей
yqТот же язык фильтров, но для YAMLМанифесты Kubernetes и CI-конфиги; для быстрой конвертации YAML↔JSON в браузере попробуйте наши YAML → JSON и JSON → YAML
Форматировщик JSON в браузереПодсветка, точные ошибки, ноль установкиОтладка одного ответа во время разработки

Для повседневной shell-работы jq побеждает за счёт композиции. Для одноразового изучения часто быстрее gron. Для YAML — yq, не пытайтесь пайпить через yq-then-jq.

Pro-советы для повседневного использования

Несколько привычек, благодаря которым jq ощущается родным:

  1. Держите .jqrc в $HOME. Положите туда вспомогательные функции — они будут доступны в каждом запуске jq:

    def running: select(.status.phase == "Running");
    def table(f): [f] | @tsv;
  2. Используйте jqplay.org для сложных фильтров. Слева вставьте JSON, справа итерируйте фильтр, рабочую версию переносите в скрипт.

  3. Соберите свою шпаргалку из history. history | grep 'jq ' | sort -u > ~/jq-patterns.txt фиксирует каждый паттерн, который вы реально использовали.

  4. Сочетайте с форматировщиком JSON в браузере для незнакомых схем. Сначала визуально изучите структуру, найдите нужный путь, потом напишите команду jq.

  5. Наблюдайте живые значения: watch -n 5 "curl -s api.example.com/health | jq '.uptime'" обновляется каждые 5 секунд — быстрый ops-дашборд без зависимостей.

FAQ

Что такое jq и зачем разработчики его используют?

jq — это процессор JSON для командной строки. Извлекает, фильтрует и преобразует JSON внутри shell-пайплайнов без скрипта на Python или Node — самый быстрый путь от ответа API, лог-файла или вывода kubectl к нужному полю.

jq доступен в Windows?

Да. Установка через winget install jqlang.jq, через Chocolatey choco install jq или скачайте бинарь с jqlang.org. Правила экранирования в PowerShell отличаются от bash — в сомнительных случаях сохраняйте фильтр в .jq-файл и запускайте jq -f filter.jq.

Чем jq отличается от форматировщика JSON в браузере?

Форматировщик JSON в браузере интерактивен — вставьте JSON, увидьте подсветку и ошибки, скопируйте результат. jq не интерактивен — описываете преобразование один раз и запускаете на shell-пайплайне. Браузер — для отладки одного ответа; jq — чтобы автоматизировать ту же операцию по сотням.

Почему jq говорит «Cannot iterate over null»?

Вы попытались итерировать (.[]) по значению, которое null, обычно потому что поле отсутствовало во входе. Исправляется optional-оператором .items[]? или значением по умолчанию .items // [] | .[].

Может ли jq менять файлы на месте?

Напрямую нет — jq пишет в stdout. Используйте временный файл или sponge из moreutils: jq '.version = "2.0"' config.json | sponge config.json. Всегда делайте резервную копию исходника; опечатка в фильтре перезапишет файл.

Как использовать jq с ответами curl?

Пайпите curl -s в jq. Флаг -s глушит индикатор прогресса curl, поэтому до jq доходит только тело JSON:

curl -s https://api.github.com/users/octocat | jq '.name, .blog'

В чём разница между | в jq и | в shell?

Shell-пайп шлёт байты между процессами. Пайп jq шлёт JSON-значения между фильтрами внутри одного запуска jq. Одна команда jq со многими внутренними пайпами работает в одном процессе — дешевле, чем цепочка jq | jq | jq.

Может ли jq работать с JSON Lines (NDJSON)?

Да, нативно. jq читает каждую строку как самостоятельное JSON-значение, если они разделены пробельными символами. -c выдаёт NDJSON, -s собирает NDJSON в один массив.

Как pretty-print без фильтрации?

Используйте identity-фильтр: cat data.json | jq . или просто jq . < data.json. Он парсит, валидирует и pretty-print с отступом в два пробела — без фильтра.

Есть ли альтернатива jq с GUI?

Да. fx даёт интерактивный TUI. Для GUI без установки — браузерный форматировщик JSON покрывает большинство задач explore-and-validate. Веб-инструменты вроде jqplay.org предлагают сам jq с живым предпросмотром.

Когда вместо jq лучше написать скрипт на Python?

Тяните jq, если задача одноразовая, помещается в shell-пайплайн и не выходит за рамки фильтрации, преобразования и извлечения. Переходите на Python, когда нужны юнит-тесты, сложное состояние, сторонние библиотеки или ветвления, выходящие за пределы того, что .jq-файл оставляет читаемым.

Как использовать регулярные выражения в jq?

jq предоставляет regex через test("pattern"), match("pattern"), capture("pattern") и scan("pattern"), все на синтаксисе PCRE. Флаги передаются вторым аргументом: test("abc"; "i") для case-insensitive. match возвращает смещения и захваты; scan выдаёт каждое непересекающееся совпадение.

Ключевые выводы

  1. Сначала ментальная модель: фильтр на входе, ноль или больше JSON-значений на выходе, композиция через |. Всё остальное — синтаксис.
  2. Учите по задаче, не по оператору: 30 паттернов выше покрывают примерно 95% повседневной работы с jq.
  3. Обрабатывайте null явно: ? для тихого пропуска, // default для конкретного fallback. Большинство исправлений Cannot iterate over null — одно из двух.
  4. Знайте, когда jq — неправильный инструмент: одиночные ответы — в браузерный форматировщик JSON; YAML — в yq; сложная логика — в реальный код.
  5. Сочетайте с существующим стеком: jq сияет внутри curl, kubectl, aws, docker и лог-пайплайнов. Используйте его как клей, а не как слой логики.

Связанные сценарии работы с JSON — см. руководство по форматированию JSON5 и JSONC для синтаксических расширений конфигов и руководство по конвертации CSV ↔ JSON для миграции данных, где jq встраивается в пайплайн. Когда в JSON есть таймстампы, руководство по Unix timestamp разбирает ловушки, в которые легко попасть при преобразовании дат.

Похожие статьи

Все статьи