jq ссылается на индекс/ключ с его внутренними значениями

Вопрос или проблема

У меня есть JSON, похожий на следующий:

Файл: my_data.json

{
  "hosts": {
    "1.2.3.4": { "name": "name4", "env": "test", "options": "" },
    "1.2.3.5": { "name": "name5", "env": "prod", "options": "opt1,opt2" },
    "1.2.3.6": { "name": "name6", "env": "qa", "options": "" },
    "1.2.3.7": { "name": "name7", "env": "staging", "options": "opt3,opt4" },
    "1.2.3.8": { "name": "name8", "env": "dev", "options": "opt5" },
    "1.2.3.9": { "name": "name9", "env": "prod", "options": "opt6,opt7" }
  }
}

Я хочу извлечь из этого CSV-файл, я пробовал несколько вариантов, которые нашел в Google, но ни один не сработал. Моя цель – получить что-то похожее на следующее:

"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","dev",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"

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

jq --raw-output '.hosts[] | [.name, .env, .options] | @csv' my_data.json

Вот мой результат, но, как видно, он неполный. Как мне добавить ключ к каждому объекту?

"name4","test",""
"name5","prod","opt1,opt2"
"name6","qa",""
"name7","staging","opt3,opt4"
"name8","dev","opt5"
"name9","prod","opt6,opt7"

Я сделал это:

jq --raw-output '.hosts | keys_unsorted[] | [.] | @csv' my_data.json

Но это только извлекает ключи, и я не нашел способ обратиться к объекту, используя ключ.

"1.2.3.4"
"1.2.3.5"
"1.2.3.6"
"1.2.3.7"
"1.2.3.8"
"1.2.3.9"

Я мог бы попробовать объединить обе таблицы, но это может привести к ошибкам, и я знаю, что должен быть способ сделать это в jq, но я просто не могу найти метод.

Я провел несколько поисков в Google и нашел один многообещающий, но он не работает:

jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv' my_data.json

Этот вызов возвращает ошибки компиляции:

jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at <top-level>, line 1:
.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv
jq: error: syntax error, unexpected ')', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv
jq: 2 compile errors

Используйте keys_unsorted или to_entries, чтобы получить доступ к ключам:

.hosts | keys_unsorted[] as $key
| [$key, (.[$key] | .name, .env, .options)] | @csv

Демо

или

.hosts | to_entries[]
| [.key, (.value | .name, .env, .options)] | @csv

Демо

"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"

После экспериментов с jqkungfu.com я нашел решение:

jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, .[$k].name, .[$k].env, .[$k].options] | @csv' my_data.json

Это вернет желаемый вывод:

"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"

Ответ или решение

Как использовать jq для извлечения JSON в CSV: Пошаговое руководство

Если вы работаете с JSON-файлами и хотите извлечь данные в формате CSV, jq — это мощный инструмент, который может вам помочь. В этом руководстве мы рассмотрим, как извлечь значения ключей и их внутренние значения из JSON-структуры, используя jq.

Исходные данные

Предположим, у нас есть JSON-файл my_data.json, содержащий следующую структуру:

{
  "hosts": {
    "1.2.3.4": { "name": "name4", "env": "test", "options": "" },
    "1.2.3.5": { "name": "name5", "env": "prod", "options": "opt1,opt2" },
    "1.2.3.6": { "name": "name6", "env": "qa", "options": "" },
    "1.2.3.7": { "name": "name7", "env": "staging", "options": "opt3,opt4" },
    "1.2.3.8": { "name": "name8", "env": "dev", "options": "opt5" },
    "1.2.3.9": { "name": "name9", "env": "prod", "options": "opt6,opt7" }
  }
}

Наша цель — извлечь эти данные в формате CSV, чтобы результат выглядел следующим образом:

"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"

Решение

Для достижения этой цели мы воспользуемся следующей командой jq:

jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, .[$k].name, .[$k].env, .[$k].options] | @csv' my_data.json

Разберем по шагам, как работает эта команда.

  1. --raw-output: Этот флаг обеспечивает вывод в текстовом формате без дополнительных кавычек, что полезно для создания CSV.

  2. '.hosts': Мы начинаем с корневого узла JSON и переходим к объекту hosts.

  3. keys_unsorted[] as $k: Эта часть извлекает все ключи в объекте hosts (в данном случае это IP-адреса) и сохраняет их в переменной $k.

  4. [$k, .[$k].name, .[$k].env, .[$k].options]: Создаем массив, который включает ключ $k, а также значения name, env и options, соответствующие этому ключу.

  5. @csv: Форматируем массив в виде строки CSV.

Примеры использования

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

"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"

Заключение

Использование jq для извлечения данных из JSON-файлов в формате CSV открывает широкие возможности для обработки и анализа данных. Приведенная команда является универсальным решением, которое можно адаптировать под собственные нужды, изменяя структуру JSON или формат вывода. Воспользуйтесь этой возможностью, чтобы эффективно справляться со своими данными и извлекать из них максимальную пользу.

Оцените материал
Добавить комментарий

Капча загружается...