我希望有人能指导我如何将下面的 json 转换为我期望的 csv。
提前非常感谢。
更新:感谢提供的解决方案,但我发现有时当第二列只有 1 条记录时数组不存在,下面的示例是“ASite”只有 1 条与之配对的记录“unixhost1123”。
源 json
[
{
"results": [
[
"sm-clust001",
[
"163slesm02",
"163slesm01"
]
],
[
"sm-cssl112",
[
"ucsbnchac240",
"ucsbnchac209",
"ucsbnchac241",
"ucsbnchac242"
]
],
[
"ASite",
"unixhost1123"
]
]
}
]
期待 csv
"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"
答案1
.[].results[]
是一组数组。在每个数组中,第一个元素是您想要在第一列中拥有的元素,第二个元素是我们想要循环的另一个数组。
因此,让我们跟踪第一个元素$name
(假设这是某种簇名称),然后将其与子数组的每个元素一起输出:
.[].results[] | .[0] as $name | .[1][]? // .[1] | [ $name, . ] | @csv
该位表示.[1][]? // .[1]
选择子数组的元素(如果存在),否则选择数组的第二个元素(并假设它是标量)。
在命令行上:
jq -r '.[].results[] | .[0] as $name | .[1][]? // .[1] | [ $name, . ] | @csv' file
给出您的示例文档的结果:
"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"
答案2
这可能不是我仍在学习的最优雅的解决方案jq
,但这会产生您想要的输出
jq -r '.[].results[] | { a:.[0], b:.[1][] } | [ .a, .b ] | @csv'
结果
"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
“魔力”在于管道的第二部分 ,它为第二项 ( ) 中的每一项{ a:.[0], b:.[1][] }
重复第一项( ) 。然后可以将其转换为数组列表,然后输出为 CSV。[0]
[1][]
为了处理您最近添加的最后一行示例数据,我修改了管道以将此异常值转换为与其他数据相同的形状。 (这对我来说也是一次学习练习。)
jq -r '
.[].results[] | # Concentrate only on the results[] array
[ .[0], [ .[1][]? // .[1] ] ] | # Copy through first element; force the second to be an array
{ a:.[0], b:.[1][] } | # Iterate across the second element as an array
[ .a, .b ] | # Convert the objects we have just created back into array slices
@csv # Output as CSV, remember the -r flag for jq
'
这里的加法是[ .[0], [ .[1][]? // .[1] ] ]
分量,原样通过每个块的第一个元素,然后如果第二个元素是不是数组将其转换为一。 (它解开数组,或呈现单例项,然后将结果包装到数组中。)
也曾被指出我可以修改我的原始代码,通过使用(.[1][]? // .[1])
包含 if/then 表达式来提供更优雅的解决方案,该表达式要么像以前一样迭代数组元素,要么简单地提供第二个元素(如果它不是数组):
jq -r '.[].results[] | { a:.[0], b:(.[1][]? // .[1]) } | [ .a, .b ] | @csv'
任一修改的结果
"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"
我从中学到了很多本教程,这是迄今为止我发现的最好的之一。