tkuchikiの日記

新ブログ https://blog.tkuchiki.net

jq で JSON を LTSV に変換する

結論

[
  {"foo": "bar1", "hoge": "piyo1"},
  {"foo": "bar2", "hoge": "piyo2"},
  {"foo": "bar3", "hoge": "piyo3"}
]

という json(test.json とする) があるときに、

$ cat test.json | jq -r '.[] | to_entries | map("\(.key):\(.value)") | join("\t")'

と実行すると、

foo:bar1        hoge:piyo1
foo:bar2        hoge:piyo2
foo:bar3        hoge:piyo3

と出力されます。

解説

分解して説明します。
to_entrieskey, value という key を持った hash の array に変換します。

$ cat test.json | jq -r '.[] | to_entries'
[
  {
    "key": "foo",
    "value": "bar1"
  },
  {
    "key": "hoge",
    "value": "piyo1"
  }
]
[
  {
    "key": "foo",
    "value": "bar2"
  },
  {
    "key": "hoge",
    "value": "piyo2"
  }
]
[
  {
    "key": "foo",
    "value": "bar3"
  },
  {
    "key": "hoge",
    "value": "piyo3"
  }
]

map は配列に対して処理を行え、
"(\.KEY)" で文字列変数展開ができるので、
map("\(.key):\(.value)") として Label:Value の形式に変換します。

$ cat test.json | jq -r '.[] | to_entries | map("\(.key):\(.value)")'
[
  "foo:bar1",
  "hoge:piyo1"
]
[
  "foo:bar2",
  "hoge:piyo2"
]
[
  "foo:bar3",
  "hoge:piyo3"
]

最後に、join("\t") で array を Tab 区切りの文字列に変換して完了です。

謝辞

http://stackoverflow.com/a/25378171 をちょっといじっただけです。
とても助かりました。aioobe さん、ありがとうございます!