需要 jq 帮助将半格式错误但非常简单的 json 文件转换为 csv
Need jq help to turn a semi-malformed but very simple json file into csv
我有点问题。我已经针对对象检测器吐出的一大组 json 文件尝试了 jq -r
的许多不同迭代,但我就是无法让它足够快乐地给我一个 csv 文件。我将这些庞大的文件简化为下面一个非常简短的示例,具有完全相同的数据结构(注意,诸如“书”、“人”、“动物”之类的名称在脚本中不断变化,所以如果有办法在不对命令中的键进行硬编码的情况下执行此操作,这是最需要但不是必需的)
示例:
{
"/src/files/image_1.png": {
"book": 0.01711445301771164,
"person": 0.000330559065533263624,
"place": 0.9814764857292175,
"animal": 1.8662762158783153e-05,
"vehicle": 0.0010597968939691782
},
"/src/files/image_2.png": {
"book": 0.23741412162780762,
"person": 0.1587823033328247,
"place": 0.59659236669504,
"animal": 0.0036556862760335207,
"vehicle": 0.003555471543222666
}
}
理想情况下,我想制作一个表格格式如下所示的 csv 文件:
File
Book
Person
Place
Animal
Vehicle
/src/files/image_1.png
0.01711445301771164
0.000330559065533263624
0.9814764857292175
1.8662762158783153e-05
0.0010597968939691782
/src/files/image_2.png
0.23741412162780762
0.1587823033328247
0.59659236669504
0.0036556862760335207
0.003555471543222666
. as $data |
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( $ids[] | [ ., $data[.][$fields[]] ] )
) | @csv
或
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( to_entries[] | [ .key, .value[$fields[]] ] )
) | @csv
两者都不能很好地处理空输入 ({}
)。
为了比较,@peak 的 headers 解决方案是
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( $ids[] as $id | [ $id, .[$id][$fields[]] ] )
) | @csv
它也不能很好地处理空输入 ({}
)
下面的解决方案比其他方式更棘手,因为它是“data-driven”(在 jq 程序中 hard-coded 除了“文件”之外没有其他键名),同时不假设内部键的顺序一致:
keys_unsorted as $outer
| (.[$outer[0]] | keys_unsorted) as $inner
| ["File"] + ($inner|map((.[:1]|ascii_upcase) + .[1:])),
($outer[] as $k
| [$k] + [.[$k] | .[$inner[]]])
| @tsv
您当然希望使用 @csv
而不是 @tsv
。
(有许多 SO 问题说明了如何添加 headers,例如,以下说明如何在不对它们进行硬编码的情况下添加它们,并在主要 [= 下方动态生成“-”行22=]: How to format a JSON string as a table using jq?)
我有点问题。我已经针对对象检测器吐出的一大组 json 文件尝试了 jq -r
的许多不同迭代,但我就是无法让它足够快乐地给我一个 csv 文件。我将这些庞大的文件简化为下面一个非常简短的示例,具有完全相同的数据结构(注意,诸如“书”、“人”、“动物”之类的名称在脚本中不断变化,所以如果有办法在不对命令中的键进行硬编码的情况下执行此操作,这是最需要但不是必需的)
示例:
{
"/src/files/image_1.png": {
"book": 0.01711445301771164,
"person": 0.000330559065533263624,
"place": 0.9814764857292175,
"animal": 1.8662762158783153e-05,
"vehicle": 0.0010597968939691782
},
"/src/files/image_2.png": {
"book": 0.23741412162780762,
"person": 0.1587823033328247,
"place": 0.59659236669504,
"animal": 0.0036556862760335207,
"vehicle": 0.003555471543222666
}
}
理想情况下,我想制作一个表格格式如下所示的 csv 文件:
File | Book | Person | Place | Animal | Vehicle |
---|---|---|---|---|---|
/src/files/image_1.png | 0.01711445301771164 | 0.000330559065533263624 | 0.9814764857292175 | 1.8662762158783153e-05 | 0.0010597968939691782 |
/src/files/image_2.png | 0.23741412162780762 | 0.1587823033328247 | 0.59659236669504 | 0.0036556862760335207 | 0.003555471543222666 |
. as $data |
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( $ids[] | [ ., $data[.][$fields[]] ] )
) | @csv
或
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( to_entries[] | [ .key, .value[$fields[]] ] )
) | @csv
两者都不能很好地处理空输入 ({}
)。
为了比较,@peak 的 headers 解决方案是
keys_unsorted as $ids |
( .[ $ids[0] ] | keys_unsorted ) as $fields |
(
[ "id", $fields[] ],
( $ids[] as $id | [ $id, .[$id][$fields[]] ] )
) | @csv
它也不能很好地处理空输入 ({}
)
下面的解决方案比其他方式更棘手,因为它是“data-driven”(在 jq 程序中 hard-coded 除了“文件”之外没有其他键名),同时不假设内部键的顺序一致:
keys_unsorted as $outer
| (.[$outer[0]] | keys_unsorted) as $inner
| ["File"] + ($inner|map((.[:1]|ascii_upcase) + .[1:])),
($outer[] as $k
| [$k] + [.[$k] | .[$inner[]]])
| @tsv
您当然希望使用 @csv
而不是 @tsv
。
(有许多 SO 问题说明了如何添加 headers,例如,以下说明如何在不对它们进行硬编码的情况下添加它们,并在主要 [= 下方动态生成“-”行22=]: How to format a JSON string as a table using jq?)