jq One-Liners Фильтрация и преобразование JSON из командной строки без написания скрипта
Семь практических рецептов jq для разработчиков backend и DevOps — охватывает select, map, to_entries, del, group_by и реальную перестройку API. Показаны входные и выходные данные для каждого шаблона.
Вы смотрите на сжатый ответ API в терминале. Вам нужно извлечь 3 поля, отфильтровать нулевые значения и направить результат в другое приложение. Написание скрипта на Python для этого требует 20 строк и 2 минуты, которых у вас нет. jq обрабатывает это за одну команду — если вы знаете соответствующие шаблоны.
Семь рецептов ниже. Каждый из них охватывает шаблон, который вы будете часто встречать при работе с ответами API или лог-файлами. Показаны входные данные, команда и выходные данные для каждого рецепта.
Установка
brew install jq # macOS
apt-get install jq # Ubuntu/Debian
apk add jq # Alpine (Docker images)
Рецепт 1: Извлечение поля из каждого объекта в массиве
Наиболее распространённая операция, которую вы будете выполнять с jq: извлечение одного поля из каждого элемента в массиве JSON.
Входные данные (users.json)
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"},
{"id": 2, "name": "Bob", "email": "bob@example.com", "role": "user"},
{"id": 3, "name": "Carol", "email": "carol@example.com", "role": "user"}
]
jq '.[].name' users.json
# → "Alice"
# "Bob"
# "Carol" (newline-separated stream)
.[] проходит по каждому элементу в массиве; .name извлекает поле. Результат — поток, который полезен для передачи в другие команды. Если вам нужно получить корректный массив JSON обратно:
jq 'map(.name)' users.json
# → ["Alice", "Bob", "Carol"]
map(.name) сокращение означает [.[] | .name] — применяет выражение к каждому элементу и обёртывает результаты в массив. Вы будете часто использовать map() .
Рецепт 2: Фильтрация с помощью select
Оставляйте только объекты, соответствующие определённому условию; удаляйте остальные.
jq 'map(select(.role == "admin"))' users.json
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"}
]
select(expr) передаёт элемент только тогда, когда выражение является истинным — все остальные исчезают. Обёртывание его в map() сохраняет выходной массив. Дополнительные примеры:
# Numeric comparison
jq 'map(select(.score > 80))' results.json
# Not-null check
jq 'map(select(.error != null))' events.json
# String contains (requires test)
jq 'map(select(.message | test("timeout")))' logs.json
Рецепт 3: Изменение структуры объектов с помощью map
Выбираете только необходимые поля и при необходимости переименовываете их в одном проходе.
jq 'map({name: .name, role: .role})' users.json
[
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"},
{"name": "Carol", "role": "user"}
]
Вы создаёте новый объект для каждого элемента. Чтобы переименовать ключ, измените левую часть двоеточия:
jq 'map({username: .name, access_level: .role})' users.json
Одна сокращённая форма, которая экономит ввод: {name} эквивалентна {name: .name}. Если вы хотите, чтобы поле осталось без изменений, вам не нужно писать ключ дважды:
jq 'map({id, name, role})' users.json
Рецепт 4: Переименование ключей с помощью to_entries и from_entries
map подходит, когда вы знаете, какие ключи существуют. Когда вам нужно преобразовать сами ключи — добавить префикс, изменить соглашения о названиях или переименовать на основе соответствия — to_entries является правильным шаблоном.
Входные данные (config.json)
{"api_url": "https://api.example.com", "timeout": 30, "retry_count": 3}
# Add cfg_ prefix to every key
jq 'to_entries | map(.key = "cfg_" + .key) | from_entries' config.json
{"cfg_api_url": "https://api.example.com", "cfg_timeout": 30, "cfg_retry_count": 3}
to_entries преобразует {"k": "v"} в [{"key": "k", "value": "v"}]. После того, как вы изменяете элементы в получившемся массиве, from_entries восстанавливает объект. Чтобы переименовать один конкретный ключ без изменения других:
jq 'to_entries | map(if .key == "api_url" then .key = "endpoint" else . end) | from_entries' config.json
Рецепт 5: Удаление полей с помощью del
Противоположность изменению структуры: сохраняйте всё и удалите несколько конкретных полей. Основное применение — удаление чувствительных данных перед логированием или перед передачей нагрузки третьим сторонам.
jq 'map(del(.email))' users.json
[
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"},
{"id": 3, "name": "Carol", "role": "user"}
]
Удалите несколько полей одновременно или удалите вложенные пути:
# Multiple top-level fields at once
jq 'del(.password, .token, .refresh_token)' user.json
# Nested path
jq 'del(.user.internal_id)' response.json
# All fields named "debug" at any depth (recursive descent)
jq 'del(.. | .debug? // empty)' response.json
Рецепт 6: Фильтрация, изменение структуры и сортировка за один проход
Реальная ценность — это последовательное использование этих примитивов. Ниже приведён шаблон, который часто встречается при работе с пагинированными ответами API: проникнуть в вложенный массив, отфильтровать его, изменить объекты и отсортировать результат.
Входные данные (repos.json)
{
"total_count": 3,
"items": [
{"id": 1, "name": "repo-alpha", "stargazers_count": 142, "language": "Go", "private": false},
{"id": 2, "name": "repo-beta", "stargazers_count": 89, "language": "Python", "private": true},
{"id": 3, "name": "repo-gamma", "stargazers_count": 310, "language": "Go", "private": false}
]
}
jq '.items
| map(select(.private == false and .language == "Go"))
| sort_by(-.stargazers_count)
| map({name, stars: .stargazers_count})' repos.json
[
{"name": "repo-gamma", "stars": 310},
{"name": "repo-alpha", "stars": 142}
]
Последовательность команд:
.items— проникнуть в вложенный массивmap(select(...))— отфильтровать за один проход;andсоединяет условияsort_by(-.stargazers_count)— отрицает значение для сортировки в порядке убывания;sort_by(.field)одна операция даёт сортировку в порядке возрастанияmap({name, stars: .stargazers_count})— финальное изменение структуры;{name}сокращение означает{name: .name}
Рецепт 7: Подсчёт уровней логов с помощью group_by
Анализ частоты в структурированном выводе логов — без базы данных, без сложных операций с awk.
Входные данные (logs.json)
[
{"level": "error", "msg": "connection timeout", "service": "auth"},
{"level": "info", "msg": "request received", "service": "api"},
{"level": "error", "msg": "null pointer exception", "service": "worker"},
{"level": "warn", "msg": "slow query detected", "service": "db"},
{"level": "error", "msg": "rate limit exceeded", "service": "api"}
]
jq 'group_by(.level) | map({level: .[0].level, count: length}) | sort_by(-.count)' logs.json
[
{"level": "error", "count": 3},
{"level": "info", "count": 1},
{"level": "warn", "count": 1}
]
group_by(.level) возвращает массив из массивов — каждый подмассив содержит все записи, имеющие одинаковое значение уровня. .[0].level извлекает имя уровня из первого элемента группы; length подсчитывает количество записей в группе.
Добавьте разбивку по сервисам в том же запросе:
jq 'group_by(.level) | map({
level: .[0].level,
count: length,
services: map(.service) | unique
})' logs.json
Скорое руководство
Таблица с описанием вышеуказанных шаблонов для случаев, когда вам нужно быстро напомнить:
| Что вы хотите | выражение jq |
|---|---|
| Все значения поля | map(.field) |
| Фильтрация соответствующих элементов | map(select(.field == "val")) |
| Изменение структуры каждого объекта | map({newKey: .oldKey}) |
| Переименование всех ключей | to_entries | map(.key = ...) | from_entries |
| Удаление полей | map(del(.field1, .field2)) |
| Сортировка по возрастанию | sort_by(.field) |
| Сортировка по убыванию | sort_by(-.field) |
| Подсчёт по группам | group_by(.field) | map({key: .[0].field, count: length}) |
| Получение всех ключей объекта | keys |
| Подсчёт элементов в массиве | length |
| Уникальные значения поля | map(.field) | unique |
Перед началом: Управляйте большим объёмом данных
Ответы API часто приходят в сжатом или глубоко вложённом виде. Если вы не уверены в нужном пути, вставьте JSON в Форматировщик JSON — он красиво отформатирует с сжатыми узлами, чтобы вы могли определить путь до написания выражения jq . После выполнения преобразования, инструмент полезен для проверки разницы до и после, когда вы изменяете или удаляете поля и хотите убедиться, что ничего не изменилось неожиданно. JSON-сравнение Эти семь шаблонов охватывают большую часть операций с JSON, которые вы будете выполнять в командной строке. Реальная сила — это последовательное использование этих шаблонов — как только вы сможете фильтровать, изменять структуру и сортировать, вы сможете обрабатывать большинство ответов API без обращения к скрипту.
jq One-Liners: Фильтрация и преобразование JSON из командной строки без написания скрипта 2
Установите наши расширения
Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска
恵 Табло результатов прибыло!
Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!
Подписаться на новости
все Новые поступления
всеОбновлять: Наш последний инструмент был добавлен 8 июня 2026 года
