🗒️
jq コマンドで JSON を CSV に変換する
前置き
まとまった JSON データはあるが欲しいデータをお手軽に取り出したいとき、jq
を使うと JSON に対してクエリをかける形で値を取り出せる。もっと欲を出して、出力結果を CSV にしてやりたいこともある。これも jq の範囲で対応可能である。
要約
以下のいずれかで良い。基本的には前者で問題なく、クォーテーションを省きたい場合は後者を使う(ただし注意点あり)。
cat test.json | jq -r '["uuid", "ipv4"], (.[] | [.uuid, .ipv4]) | @csv'
echo uuid,ipv4 && cat test.json | jq -r '.[] | "\(.uuid),\(.ipv4)"'
サンプルデータ
[
{
"uuid": "3861facf-939a-42ee-bb7d-3acf16deec22",
"ipv4": "155.31.192.229"
},
{
"uuid": "17cb6f50-69a9-4f89-803d-f8d08cb71ab0",
"ipv4": "252.7.186.75"
},
{
"uuid": "b09a19aa-3306-41dc-a76a-b305e763010a",
"ipv4": "5.203.192.193"
},
{
"uuid": "3cc3d20c-8b01-428c-8ead-7398aab3a55d",
"ipv4": "79.52.14.188"
},
{
"uuid": "90617d94-9cd5-4c01-9b39-1e8340afa046",
"ipv4": "0.198.93.99"
}
]
1. @csv オペレータを使う
確実かつ簡単。ただし jq の式はちょっとテクニカルになる。要領は次の通り。
- 見出し行を出力するために、見出し行を表現した配列と JSON を変換した配列を結合させる
- jq で一旦 JSON の各要素を配列に加工したうえで、
@csv
を配列に適用させる
❯ cat test.json | jq -r '["uuid", "ipv4"], (.[] | [.uuid, .ipv4]) | @csv'
uuid,ipv4
"3861facf-939a-42ee-bb7d-3acf16deec22","155.31.192.229"
"17cb6f50-69a9-4f89-803d-f8d08cb71ab0","252.7.186.75"
"b09a19aa-3306-41dc-a76a-b305e763010a","5.203.192.193"
"3cc3d20c-8b01-428c-8ead-7398aab3a55d","79.52.14.188"
"90617d94-9cd5-4c01-9b39-1e8340afa046","0.198.93.99"
2. 手前味噌でフォーマットする
見た目だけだと @csv を使うよりは直感的かもしれない。
この方法では jq が JSON をフォーマットした形で出力できることを利用して、CSVっぽくする。副作用的になるが、この場合だと各値が "
で囲わられなくなる。
ただし問題もあり、例えば「素直な」JSON なら大丈夫だが JSON の値に変な文字(特にカンマ)が含まれていると CSV が壊れる。上述のサンプルみたいに出力形式が固まっているものだけをターゲットにするなら問題ない。
(2) の場合、見出し行の処理は jq ではなく echo で代理し、jq の式も少しいじることになる。
❯ echo uuid,ipv4 && cat test.json | jq -r '.[] | "\(.uuid),\(.ipv4)"'
uuid,ipv4
3861facf-939a-42ee-bb7d-3acf16deec22,155.31.192.229
17cb6f50-69a9-4f89-803d-f8d08cb71ab0,252.7.186.75
b09a19aa-3306-41dc-a76a-b305e763010a,5.203.192.193
3cc3d20c-8b01-428c-8ead-7398aab3a55d,79.52.14.188
90617d94-9cd5-4c01-9b39-1e8340afa046,0.198.93.99
Discussion