如何jq嵌套数组没有键(只有值)并转换为csv

如何jq嵌套数组没有键(只有值)并转换为csv

我希望有人能指导我如何将下面的 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"

我从中学到了很多本教程,这是迄今为止我发现的最好的之一。

相关内容