Как сопоставить объект с массивами, чтобы его можно было преобразовать в csv?
Я пытаюсь преобразовать объект, который выглядит так:
{
"123" : "abc",
"231" : "dbh",
"452" : "xyz"
}
В csv, который выглядит следующим образом:
"123","abc"
"231","dbh"
"452","xyz"
Я бы предпочел использовать инструмент командной строки jq, но, похоже, не может понять, как выполнить назначение. Мне удалось получить ключи с jq '. | keys' test.json
, но не могли понять, что делать дальше.
Проблема в том, что вы не можете преобразовать объект k: v, подобный этому, прямо в csv с помощью @csv
. Он должен быть массивом, поэтому нам нужно сначала преобразовать в массив. Если бы клавиши были названы, это было бы просто, но они динамичны, поэтому это не так просто.
Ответы
Ответ 1
Попробуйте этот фильтр:
to_entries[] | [.key, .value]
-
to_entries
преобразует объект в массив объектов key/value. []
разбивает массив на каждый из элементов массива
- затем для каждого из элементов, скрытых для массива, содержащего ключ и значение.
Это приводит к следующему выводу:
[
"123",
"abc"
],
[
"231",
"dbh"
],
[
"452",
"xyz"
]
Затем вы можете использовать фильтр @csv
для преобразования строк в строки CSV.
$ echo '{"123":"abc","231":"dbh","452":"xyz"}' | jq -r 'to_entries[] | [.key, .value] | @csv'
"123","abc"
"231","dbh"
"452","xyz"
Ответ 2
Вот пример, который я использовал сегодня утром (обработка оповещений PagerDuty):
cat /tmp/summary.json | jq -r '
.incidents
| map({desc: .trigger_summary_data.description, id:.id})
| group_by(.desc)
| map(length as $len
| {desc:.[0].desc, length: $len})
| sort_by(.length)
| map([.desc, .length] | @csv)
| join("\n") '
Сбрасывает документ, разделенный CVS, который выглядит примерно так:
"[Triggered] Something annoyingly frequent",31
"[Triggered] Even more frequent alert!",35
"[No data] Stats Server is probably acting up",55
Ответ 3
Ответ Джеффа - хорошая отправная точка, что-то ближе к ожидаемому:
cat input.json | jq 'to_entries | map([.key, .value]|join(","))'
[
"123,abc",
"231,dbh",
"452,xyz"
]
Но не удалось найти способ соединения с использованием новой строки:
cat input.json | jq 'to_entries | map([.key, .value]|join(","))|join("\n")'
"123,abc\n231,dbh\n452,xyz"
Ответ 4
onecol2txt () {
awk 'BEGIN { RS="_end_"; FS="\n"}
{ for (i=2; i <= NF; i++){
printf "%s ",$i
}
printf "\n"
}'
}
cat jsonfile | jq -r -c '....,"_end_"' | onecol2txt