2016/08/05

Recent entries from same category

  1. Go 言語プログラミングエッセンスという本を書きました。
  2. errors.Join が入った。
  3. unsafe.StringData、unsafe.String、unsafe.SliceData が入った。
  4. Re: Go言語で画像ファイルか確認してみる
  5. net/url に JoinPath が入った。

昨日僕の Twitter タイムラインで q というツールが話題に上がっていました。

GitHub - harelba/q: q - Run SQL directly on CSV or TSV files

Text as Data q is a command line tool that allows direct execution of SQL-like q...

https://github.com/harelba/q

標準入力を SQL で抽出できるという物です。ただ個人的には「こういうの python じゃなくて Go でビルドされてると助かるよなー」と思ったので q と同じ様な動作になるツールを作ってみました。

GitHub - mattn/qq

Select stdin with query

https://github.com/mattn/qq

例えば msys2 のシェル上で ps を実行すると以下の様になりますが

$ ps
      PID    PPID    PGID     WINPID   TTY         UID    STIME COMMAND
     4876    2000    4876      13840  pty1     1061251 18:31:09 /usr/bin/ps
     2000   11384    2000       8804  pty1     1061251 18:30:45 /usr/bin/bash
    11384       1   11384      11384  ?        1061251 18:30:45 /usr/bin/mintty
     7552   13692   13692       9428  pty0     1061251 17:51:39 /usr/bin/ssh
    13692   12148   13692      18360  pty0     1061251 17:51:39 /usr/bin/ssh
     7828       1    7828       7828  ?        1061251 16:11:41 /usr/bin/ssh-agent
    12148       1   12148      12148  ?        1061251 17:51:39 /usr/bin/mintty

これを qq に食わせると

$ ps | qq -q 'select pid from stdin'
2000
11384
9596
7552
13692
7828
12148

この様に表形式のコマンド出力を SQL で抽出ます。

q と違う所は、日本語の幅をきちんと見ている所です。

aaa bb
a b あ

この様なテキストの場合、カラム aaa には a b が、カラム bb には が入る事を期待してしまいます。q の場合

$ cat nihongo.txt | q -H 'select bb from -'
b

この様にカラム bb には b が入っていますが、qq だと

$ cat nihongo.txt | qq -q 'select bb from stdin'

が格納されています。q の場合、日本語が多く混じると異なるカラムに値が入ってしまいますが、qq だと大丈夫。また qq では q と同じ動作にさせる事もできます。-ip オプションでデリミタを正規表現として渡せるので

$ cat nihongo.txt | qq -ip '\s+' -q 'select bb from stdin'
b

こうすれば b が得られます。また -ic オプションを付けるとカンマセパレータの CSV (ダブルクオート可)で、-it でタブセパレートな TSV で入力データを扱う事ができます。さらに -e オプションでエンコーディング名を指定できるので Windows の Excel で作った CSV ファイルでも安心して扱えます。

品目,単価
みかん,120
りんご,100
トマト,180
$ cat meisai.csv | qq -ic -e cp932 -q "select 単価 from stdin where 品目 = 'みかん'"
120
出力フォーマットはデフォルトが CSV です。-oh を付けるとヘッダカラムが出力されます。-oj を付けると JSON 形式で出力されるのでシステムの一部として使う事も出来るかもしれません。また -or で raw 出力しますので、 $ ps | qq -q "select pid from stdin where command = '/usr/bin/grep'" | xargs kill

の様に awk や grep の代わりに使う事もできます。もちろん golang なのでバイナリ1つで動きますし、python が無い環境でも動きます。SQL なので grep では難しい抽出方法も可能ですね。

最初は q を golang に移植するだけのつもりでしたが、思ったより便利そうなので公開してみました。よろしければどうぞお使い下さい。

後で引数からファイルを取ってunionとか出来る様にする予定なので、その場合は標準入力と区別するために - を採用する予定です。その場合、実行方法が上記の記事と異なる可能性があります。

Posted at by