CSVとJSONを処理するコマンドラインツールMillerをFreeBSD 10.2で使ってみる。

MillerがJSONを使えるようになった、というツイートが流れてきて、へー、と思って見てました。

MillerはCSV版のjqを目指す、と銘打って開発されたコマンドです(たしか)。実はけっこう前から知ってたんですが、開発者がASCIIしか扱わない!と言っていて日本語圏で使うのはつらいかなーと諦めてました。

が、今みると、

Miller handles strings with any characters other than 0x00 or 0xff, using explicit UTF-8-friendly string-length computations. (I have no plans to support UTF-16 or ISO-8859-1.) (http://johnkerl.org/miller/doc/internationalization.html

という記述に変わってました。いつの間に…!

ということで、ちょっくらビルドしてみました。

ドキュメントはこれ↓

必要パッケージのインストール

FreeBSDでは次期バージョン?でportに入るらしいですが、今はないみたいなのでソースからビルドします。まずはgmakeを入れときます。

sudo pkg install gmake

アーカイブをとってくる

curl -L https://github.com/johnkerl/miller/archive/v3.4.0.tar.gz -o miller.tar.gz
tar xf miller.tar.gz
cd miller-3.4.0/

Makefileの修正

FreeBSDはclangなのでgccを使ってる部分を修正しないといけません。Makefile.no-autoconfigっていうのがいろんなところに散らばってるんですが、修正しないといけないのは、c/Makefile.no-autoconfigc/dsls/Makefile.no-autoconfigみたいです。

cd c/
sed -i 's/CC=gcc/CC=clang/' Makefile.no-autoconfig dsls/Makefile.no-autoconfig

make

試してないけど、シンプルなのでひょっとするとgmakeじゃなくてmakeでも大丈夫だったのかも。

gmake -f Makefile.no-autoconfig
sudo Makefile.no-autoconfig install

試してみる

試しに、Github APIを叩いて、hadleyのレポジトリで星が50個以上のやつを探してみます。

詳細は割愛しますが、Millerのコマンドmlrは、

mlr [入出力の形式オプション] verb [verbごとのオプション] [ファイル名1...]

という感じになっています。verbの一覧はmlr -lで、各verbの説明はmlr verb -hで見れます。

入出力の形式が同じ場合は--jsonのように指定します。入出力で異なる場合は、入力を--iXXX、出力を--oXXXという形式で指定します。verbは色々ありますが、今回は行を絞り込むfilterと列を絞り込むcut(これはdplyrで言うとselectにあたる)を使います。

こんな感じ。

% curl https://api.github.com/users/hadley/repos \
  | mlr --json filter '$stargazers_count > 50' \
  | mlr --ijson --ocsv cut -f name,stargazers_count
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  151k  100  151k    0     0  80327      0  0:00:01  0:00:01 --:--:-- 80358
name,stargazers_count
adv-r,681
assertthat,55
bigvis,225
data-baby-names,85
data-movies,59

うーん、なんか一部だけしか取れてないけど、APIから取れるたぶんレコード数に制限があるのかな? でもまあ使えました。

感想

jqの謎文法を覚えるのに辟易していたんですが、これならいいかも。ただ、ネストしたJSONとかは扱えないみたいなので、そこはjqとかRとかで処理する必要がありそうです。

とりあえずしばらく使ってみようかなという感じ。