@csvフィルターでCSV形式に変換する

@csvフィルターを使用すると、配列をCSV形式の1行に変換できる。

$ echo '["a", "b,c", "d\"e"]' | jq -r '@csv'
"a","b,c","d""e"

カンマを含む値はダブルクオートで囲まれ、ダブルクオート自体は""にエスケープされる。

-rオプションを指定しない場合、出力全体がJSON文字列としてエスケープされてしまうため、@csv-rオプションと組み合わせて使用する。

$ echo '["a", "b,c"]' | jq '@csv'
"\"a\",\"b,c\""

@tsvフィルターでTSV形式に変換する

@tsvフィルターを使用すると、配列をタブ区切り(TSV形式)の1行に変換できる。

$ printf '["a", "b\\tc", "d"]' | jq -r '@tsv'
a	b\tc	d

値に含まれるタブ・改行・バックスラッシュは、区切り文字と衝突しないよう\t\n\\にエスケープされる。

オブジェクトの配列をCSVに変換する

.[]でオブジェクトの配列を1件ずつ取り出し、必要なフィールドだけを配列にしてから@csvに渡すとCSVの各行になる。

$ echo '[{"name": "foo", "age": 20}, {"name": "bar", "age": 30}]' | jq -r '.[] | [.name, .age] | @csv'
"foo",20
"bar",30

ヘッダー行を付けて出力する

ヘッダー行の配列と本体の配列をまとめて@csvに通すと、ヘッダー付きのCSVを1回のコマンドで出力できる。

$ echo '[{"name": "foo", "age": 20}, {"name": "bar", "age": 30}]' | \
  jq -r '(["name", "age"]), (.[] | [.name, .age]) | @csv'
"name","age"
"foo",20
"bar",30

>でリダイレクトすればそのままCSVファイルとして保存できる。

$ echo '[{"name": "foo", "age": 20}, {"name": "bar", "age": 30}]' | \
  jq -r '(["name", "age"]), (.[] | [.name, .age]) | @csv' > output.csv

注意点

数値・真偽値・nullも扱える

配列の要素は文字列に限らず、数値・真偽値・nullも変換できる。nullは空文字列になる。

$ echo '[true, false, null, 1.5]' | jq -r '@csv'
true,false,,1.5

配列やオブジェクトはそのままでは変換できない

配列の要素にネストした配列やオブジェクトが含まれる場合はエラーになる。あらかじめ文字列や数値に変換しておく必要がある。

$ echo '[{"a": 1}]' | jq -r '@csv'
jq: error (at <stdin>:1): object ({"a":1}) is not valid in a csv row