昨日僕の 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とか出来る様にする予定なので、その場合は標準入力と区別するために -
を採用する予定です。その場合、実行方法が上記の記事と異なる可能性があります。