jq ぽい何か を書いてみた

no extension

ウソです。 ほとんど自力じゃありません(笑)

JSON データを操作できる jq はとても高機能で使い勝手もいいのだが,純粋にフィルタとして機能するため Windows 環境では微妙に使いづらい場合がある。 具体的には

  • 入力が標準入力のみなのでリダイレクトやパイプと組み合わせる必要がある
  • 対話モードがない

といったところ。 大した問題ではないのだがどうにかならないかなぁ,と思っていた。

んで,どなたか Go 言語で書いている人がいるんじゃないかと思って探してみたら以下のツール/パッケージを見つけた。

simeji/jid はよく出来ていると思うのだが,残念なことに ConEmu 上で動かすと表示がぶっ壊れる(コマンドプロンプトでは問題ない)。 savaki/jqapang1992/jq はパッケージだが,ここ2,3年は更新されていないようである。

私が Windows を捨てれば simeji/jid で全然 OK なのだが(そのうち捨てる),鼻の先はそういうわけにもいかないので,自分用に CLI を書いてみることにした。

コマンドライン・オプションは以下の通り。

$ gjq -h
Usage:
  gjq [flags] <filter string>

Flags:
      --debug         for debug
  -f, --file string   JSON data (file path)
  -h, --help          help for gjq
  -i, --indent int    indent size for formatted JSON string (default 2)
  -I, --interactive   interactive mode
  -t, --tab           use tabs for indentation
  -u, --url string    JSON data (URL)
  -v, --version       output version of gjq

パーサには savaki/jq を使っている。 フィルタの文法は以下の通り。

syntax meaning
. unchanged input
.foo value at key
.foo.bar value at nested key
.[0] value at specified element of array
.[0:1] array of specified elements of array, inclusive
.foo.[0] nested value

まずは jq と同じようにフィルタとして使うならこんな感じ。

$ cat testdata/test.json
{
  "string": "a",
  "number": 1.23,
  "simple": ["a", "b", "c"],
  "mixed": [
    "a",
    1,
    {"hello":"world"}
  ],
  "object": {
    "first": "joe",
    "array": [1,2,3]
  }
}

$ gjq .object.array < testdata/test.json
[
  1,
  2,
  3
]

$ cat testdata/test.json | gjq .mixed
[
  "a",
  1,
  {
    "hello": "world"
  }
]

インデントは -i オプションで調整できるが 0 をセットすると

$ gjq -i 0 .mixed < testdata/test.json
["a",1,{"hello":"world"}]

とコンパクトになる。

また -f オプションでファイルを直接指定することもできる。

$ gjq -f testdata/test.json .object.array
[
  1,
  2,
  3
]

さらに -u オプションで URL を指定すれば Web 上のファイルも対象になる1

$ gjq -u https://text.baldanders.info/index.json .entry.[0]
{
  "title": "猫を殺すに猫を以ってせよ",
  "section": "remark",
  "description": "分かるかな。分っかんねーだろうな(反語)",
  "author": "Spiegel",
  "license": "http://creativecommons.org/licenses/by-sa/4.0/",
  "url": "https://text.baldanders.info/remark/2019/03/no-cat-no-life/",
  "published": "2019-03-11T13:51:41+00:00",
  "update": "2019-03-11T13:53:40+00:00"
}

さらにさらに -I オプションを付けると対話モードになる。

$ gjq -u https://text.baldanders.info/index.json -I
Press Ctrl+C to stop
Filter> .title
"text.Baldanders.info"
Filter> .entry.[0]
{
  "title": "猫を殺すに猫を以ってせよ",
  "section": "remark",
  "description": "分かるかな。分っかんねーだろうな(反語)",
  "author": "Spiegel",
  "license": "http://creativecommons.org/licenses/by-sa/4.0/",
  "url": "https://text.baldanders.info/remark/2019/03/no-cat-no-life/",
  "published": "2019-03-11T13:51:41+00:00",
  "update": "2019-03-11T13:53:40+00:00"
}
Filter> 

対話モードではクリップボードにも出力されるのでターミナル上でコピペする必要はない。 また JSON データは起動時に1度だけ GET するので,安心して対話モードで弄れる(笑)

さて次は色を付けてみるかな。 Go 言語でターミナル出力に色を付けるってどうやるんだろ。 調べてみるか。

参考図書

photo
プログラミング言語Go
アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)
丸善出版 2016-06-20 (Release 2021-07-13)
Kindle版
B099928SJD (ASIN)
評価     

Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想はこちら

reviewed by Spiegel on 2021-05-22 (powered by PA-APIv5)


  1. -u オプションは HTTP/HTTPS の GET で対象を取得する。 POST には対応してないのであしからず。 POST で取ってくる必要があるなら潔く curl を使ったほうがいいだろう。 ↩︎