jq — это sed для JSON: лёгкий, гибкий процессор командной строки, который превращает хаотичные ответы API и конфиг-файлы именно в те данные, которые вам нужны. Если вы когда-нибудь щурились на стену минифицированного JSON, пытаясь найти одно вложенное поле, jq — тот инструмент, который заставит вас задуматься, как вы выживали без него.
Ментальная модель проста: jq — это pipeline. Данные поступают слева, трансформируются фильтрами и выходят справа. . — ваша отправная точка, означающая «весь вход». Дальше вы углубляетесь через .field, итерируете через .[] и цепочите фильтры через |. Это функциональное программирование, замаскированное под инструмент командной строки, и как только мышление «через pipe» щёлкнет, вы будете тянуться к jq так же, как к grep.
Мы организовали шпаргалку по типу решаемой задачи, а не по внутренней таксономии jq. Начните с базовых фильтров, чтобы извлекать значения из JSON, затем переходите к операциям с массивами и объектами, когда нужно преобразовать данные. Раздел «Однострочники» в конце — вот где живёт настоящая магия: проверенные в бою паттерны, которые можно скопировать и вставить в терминал прямо сейчас.
Одну вещь стоит усвоить рано: выражения jq компонуемые. Каждый фильтр принимает вход и производит выход, поэтому их можно бесконечно цепочить через |. Тот select(...), который вы написали? Передайте его в map(...). Передайте результат в sort_by(...). Это фильтры до самого дна.
Базовые фильтры
.
Тождество — вывести весь вход без изменений.field
Извлечь поле верхнего уровня по имени.field.nested
Спуститься во вложенные объекты через точечную нотацию.["hyphenated-key"]
Обратиться к полям со спецсимволами в имени.[]
Перебрать все элементы массива или значения объекта.[0]
Получить первый элемент массива.[-1]
Получить последний элемент массива.[2:5]
Срез массива — элементы с индексами 2, 3 и 4.field?
Попробовать обратиться к полю — подавить ошибки, если оно не существует.[] | .name
Перебрать массив и извлечь поле из каждого элемента
Типы и значения
length
Длина строки, количество элементов массива или ключей объектаkeys
Получить все ключи объекта как отсортированный массивkeys_unsorted
Получить все ключи объекта в исходном порядкеvalues
Получить все значения объекта как массивtype
Вернуть тип в виде строки: "object", "array", "string", "number", "boolean" или "null"has("field")
Проверить, есть ли у объекта определённый ключ (возвращает true/false)in({"a":1})
Проверить, существует ли ключ в данном объектеempty
Не производить вывода — полезно для условного подавленияenv.VAR
Получить доступ к переменной окружения VAR
Строковые операции
split(",")
Разбить строку по разделителю в массивjoin(",")
Объединить массив строк через разделительtest("regex")
Проверить, соответствует ли строка regex (возвращает true/false)match("regex")
Вернуть объект совпадения с offset, length и capturescapture("(?<name>\\w+)")
Именованные группы захвата, возвращённые как объектgsub("old"; "new")
Заменить все вхождения regex-паттернаsub("old"; "new")
Заменить первое вхождение regex-паттернаascii_downcase
Преобразовать строку в нижний регистрascii_upcase
Преобразовать строку в верхний регистрltrimstr("prefix")
Удалить префикс из строки, если присутствуетrtrimstr("suffix")
Удалить суффикс из строки, если присутствует@base64
Закодировать строку в base64@base64d
Декодировать base64-строку@uri
Процентно закодировать строку для URL@html
Экранировать специальные символы HTMLtostring
Преобразовать любое значение в его строковое представлениеtonumber
Разобрать строку как число
Операции с массивами
map(f)
Применить фильтр f к каждому элементу и собрать результатыmap_values(f)
Применить фильтр f к каждому значению (работает и с объектами)select(condition)
Оставить только элементы, где condition истинноsort
Отсортировать массив сравнимых значенийsort_by(.field)
Отсортировать массив объектов по конкретному полюreverse
Обратить порядок массиваgroup_by(.field)
Сгруппировать элементы массива по полю в подмассивыunique
Удалить дубликаты из отсортированного массиваunique_by(.field)
Удалить дубликаты по конкретному полюflatten
Развернуть вложенные массивы в один уровеньflatten(1)
Развернуть один уровень вложенностиfirst
Получить первый выход генератораlast
Получить последний выход генератораlimit(n; expr)
Взять только первые n выходов выраженияadd
Сложить числа, конкатенировать строки или объединить массивы/объектыany(condition)
True, если хотя бы один элемент удовлетворяет условиюall(condition)
True, если все элементы удовлетворяют условиюmin_by(.field)
Получить элемент с наименьшим значением поляmax_by(.field)
Получить элемент с наибольшим значением поляindices(value)
Получить все индексы, где value встречается в массивеcontains([values])
Проверить, содержит ли массив все указанные значенияinside([values])
Проверить, содержится ли вход внутри данного значения
Операции с объектами
to_entries
Преобразовать {"a":1} в [{"key":"a","value":1}]from_entries
Преобразовать [{"key":"a","value":1}] обратно в {"a":1}with_entries(f)
Сокращение для to_entries | map(f) | from_entries+ (objects)
Объединить два объекта — правый побеждает при конфликте ключей* (objects)
Рекурсивно объединить два объекта{name, age}
Выбрать определённые поля из объекта{newname: .oldname}
Переименовать поле при извлеченииdel(.field)
Удалить поле из объектаpaths
Вывести все пути к листовым значениям как массивыgetpath(["a","b"])
Получить значение по конкретному пути — аналог .a.bsetpath(["a","b"]; val)
Установить значение по конкретному путиdelpaths([path])
Удалить значения по указанным путям
Условия и сравнения
if . then A else B end
Условное выражение — else необязателен// (alternative)
Использовать правое значение, если левое null или falsea == b
Сравнение на равенство (глубокое равенство для объектов/массивов)a != b
Сравнение на неравенствоand, or, not
Логические операторыtry f
Выполнить фильтр f, молча подавить ошибкиtry f catch msg
Выполнить фильтр f, использовать выражение msg при ошибкеf as $var | expr
Привязать значение к переменной для использования в pipelinereduce .[] as $x (init; update)
Свернуть массив в одно значениеlabel $out | foreach ...
Потоковый цикл с поддержкой break
Форматирование вывода
-r (--raw-output)
Выводить сырые строки без JSON-кавычек-c (--compact-output)
Минифицировать — вывести JSON в одну строку-S (--sort-keys)
Отсортировать ключи объекта по алфавиту в выводе-e (--exit-status)
Установить код выхода: 0 для true/non-null, 1 для false/null-n (--null-input)
Не читать вход — полезно с --argjson или --slurpfile-s (--slurp)
Прочитать все входные данные в один массив--arg name val
Передать строковое значение как переменную $name--argjson name val
Передать JSON-значение как переменную $name--slurpfile name file
Загрузить JSON-файл как переменную $name (массив)@csv
Отформатировать массив массивов как CSV@tsv
Отформатировать массив массивов как TSV@json
Сериализовать значение как JSON-строку (для встраивания)@text
Преобразовать в текстовый вывод
Однострочники
Реальные паттерны, которые вы действительно будете использовать. Копируйте, вставляйте, адаптируйте.
Однострочники
jq . file.json
Красиво вывести JSON-файлjq -r ".[] | .name" file.json
Извлечь поле из каждого объекта в массивеjq "[.[] | select(.active == true)]"
Отфильтровать массив до подходящих элементовjq -r ".[] | [.name, .email] | @csv"
Преобразовать JSON-массив в CSVjq -s "." file1.json file2.json
Объединить несколько JSON-файлов в один массивjq -r "keys[]" file.json
Вывести все ключи верхнего уровняjq ".[] | select(.price > 100) | .name"
Найти имена, где цена превышает порогjq "group_by(.status) | map({(.[0].status): length}) | add"
Подсчитать количество элементов в каждой группеjq --arg q "$QUERY" '.[] | select(.name | test($q; "i"))'
Регистронезависимый поиск с shell-переменнойjq -r "to_entries[] | \"\(.key)=\(.value)\""
Преобразовать JSON-объект в строки key=valuejq "[.[] | {id, name}]"
Преобразовать объекты — оставить только определённые поляjq -r ".results | sort_by(.date) | reverse | .[0]"
Получить самую свежую запись из отсортированного массиваcurl -s api.example.com | jq .
Красиво вывести ответ API на летуjq -s "map(.items) | flatten | unique_by(.id)"
Объединить и дедуплицировать пагинированные ответы APIjq 'walk(if type == "string" then gsub("\\n"; " ") else . end)'
Рекурсивно очистить переносы строк во всех строковых значениях
Используйте -r (raw output) каждый раз, когда передаёте вывод jq в другую команду. Без этого строки выводятся в кавычках, и эти кавычки будут преследовать ваши shell-скрипты. jq -r '.name' выдаёт Alice, а не "Alice".
Оператор // — это null coalescing в jq, он возвращает правую сторону, если левая — null или false. Идеален для значений по умолчанию: .config.timeout // 30. Это та двухсимвольная комбинация, которая в девяноста процентах случаев спасает от написания полного if-then-else.
Когда нужно объединить данные из нескольких файлов или ответов API, используйте --slurp (-s). Он читает все входные данные в один массив, и вы можете add объекты вместе, развернуть массивы или объединить данные из разных файлов.
Используйте --arg и --argjson для безопасной передачи shell-переменных в jq. Никогда не подставляйте shell-переменные напрямую в jq-выражения — это ломается на спецсимволах и открывает путь к инъекциям. jq --arg name "$USER" '.[] | select(.name == $name)' — правильный способ.
Фильтр @base64d — спасение при работе с Kubernetes secrets или JWT. Пропустите base64-значение через jq -r '.data.password | @base64d' и получите открытый текст, не выходя из pipeline.
Цепочите to_entries, map и from_entries (или используйте сокращение with_entries), чтобы трансформировать ключи и значения объекта за один проход. Хотите добавить префикс к каждому ключу? with_entries(.key = "prefix_" + .key). Это аналог map для массивов, но для объектов.
Если сообщения об ошибках jq загадочны, добавьте debug в любое место вашего pipeline, чтобы увидеть, что там течёт. Он выводит в stderr, не нарушая вывод. Думайте о нём как о console.log для jq: .[] | debug | select(.active).