キーなし(値のみ)入れ子になった配列をjqしてcsvに変換する方法

キーなし(値のみ)入れ子になった配列をjqしてcsvに変換する方法

誰かが以下のjsonを私が期待するcsvに変換する方法を案内してくれることを願っています。

よろしくお願いします。

アップデート:提供されたソリューションに感謝します。ただし、2番目の列にレコードが1つしかない場合、配列が存在しないことがあります。以下の例は、「unixhost1123」とペアになっているレコードが1つしかない「ASite」です。

ソース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[]配列のセットです。各配列では、最初の要素は最初の列に含める要素であり、2番目の要素は繰り返す別の配列です。

$nameしたがって、最初の要素(一種のクラスタ名と仮定)を追跡し、サブ配列の各要素と一緒に出力してみましょう。

.[].results[] | .[0] as $name | .[1][]? // .[1] | [ $name, . ] | @csv

このビットは、.[1][]? // .[1]サブ配列の要素がある場合に選択され、それ以外の場合は配列の2番目の要素が選択されることを示します(スカラーであると仮定)。

コマンドラインから:

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"

「魔法」は、2番目の項目()の各項目に対して{ a:.[0], b:.[1][] }最初の項目()を繰り返すパイプラインの2番目の部分にあります。その後、それを配列リストに変換して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] ] ]ごとに行われ、各ブロックの最初の要素をそのまま渡し、2番目の要素は次のとおりです。いいえ配列はこれを1に変換します。 (配列を解くか、シングルトン項目をレンダリングして結果を配列にラップします。)

また指摘(.[1][]? // .[1])前のように配列要素を繰り返すか、単に配列ではない場合は、2番目の要素を提供する埋め込み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"

私はそれから多くを学んだこのチュートリアル、これまでに見つけたものの最高の一つです。

関連情報