📋

csvの解析にはq

2022/03/04に公開

おはこんばんにちは

昔作ったシェルの改修が入ってそういやこんなんやってたなというのを思い出したので備忘録

今回紹介するqコマンドは簡単に言うとcsvファイルをテーブルとみなしてSQLで弄れるコマンドです

https://harelba.github.io/q/

で、備忘録なんでq自体の詳しい使い方は上記リンクを見てもらうとして
これどう使ったのかって内容を書いときます

ある日こんなことを言われました

👤「連携するシステムからユーザ情報を記載したこんなCSVを定期的に送ります」

渡されたCSVはこれです

$ cat test.csv
tbl,key,value
id,key1,hanako
pw,key1,hanapass
info,key1,41 years old
id,key2,taro
pw,key2,taropass
info,key2,55 years old
id,key3,nazotaro

👤「これを君んとこのDBのユーザ情報のテーブルにこんな感じで格納して下さい」

ID PW INFO
hanako hanapass 41 years old
taro taropass 55 years old
nazotaro

。。。

して下さいじゃねーよ。まず送ってくるCSVのフォーマット見直して出直してこいよ

って心の中では思いましたが

まぁこんなゴミみたいな仕様のCSVを取り込む仕事だからこそお金が発生するんだとグッと我慢してOKしました

というわけで頭が痛くなるのでその人との話は早々に切り上げてまずはCSVを確認

ふむふむ、1行目はヘッダ情報やね

テーブル名、キー、値

ってことかな?

つまりID,PW,INFOの3テーブルの情報が混在しててそれらを2カラム目のキー値で結合して3カラム目の実際のデータだけ抽出してDBと同じカラム順に出力しなおしゃええんやね

でID以外はあってもなくてもOKと。。。

つまりこうすりゃIDの一覧が出て

$ q -H -d , "select value from test.csv where tbl='id'"
hanako
taro
nazotaro

こうすりゃPWとINFOの一覧やね

$ q -H -d , "select value from test.csv where tbl='pw'"
hanapass
taropass
$ q -H -d , "select value from test.csv where tbl='info'"
41 years old
55 years old

んじゃ必須項目のIDをベースに残り2つはLEFT JOINすりゃ良さそうやね

$ q -H -d , < test.csv \
> "select ID.value,PW.value,INFO.value from - as ID left join - as PW on ID.key=PW.key and PW.tbl='pw' left join - as INFO on ID.key=INFO.key and INFO.tbl='info' where ID.tbl='id'"
hanako,hanapass,41 years old
taro,taropass,55 years old
nazotaro,,

いきなりFROM句に-使ってますがファイル名を-にすると標準入力から読み込むようになります

できたー👏

んじゃ後は適当なフォーマッタでSQLをフォーマットしてファイルに切り出して。。。

$ cat << EOF > test.sql
> select
>     ID.value,
>     PW.value,
>     INFO.value
> from
>     - as ID
>     left join
>         - as PW
>     on  ID.key = PW.key
>     and PW.tbl = 'pw'
>     left join
>         - as INFO
>     on  ID.key = INFO.key
>     and INFO.tbl = 'info'
> where
>     ID.tbl = 'id'
> EOF

んで、引数のSQL文字列をSQLファイルを読むように変更して再度実行と。。。

$ q -H -d , -q test.sql < test.csv
hanako,hanapass,41 years old
taro,taropass,55 years old
nazotaro,,

OK👌

後はこの出力をDBに流し込んで完了です

というわけでこんな感じで使ってるよという備忘録でした〜

ちなみに内部的にはsqlite3にデータ入れてから操作するような仕組みになってるみたいなのでsqliteで使えるSQL文なら使えると思います

それでは良いCSVライフを〜

しゃみしゃっきり〜

P.S.

備忘録として使うために要点に絞って簡略化しましたが実物のCSVはとんでもない量のカラムあるしDBに登録する情報ももっとあるしリレーションも複雑怪奇でこんな簡単に結合出来ないから苦肉の策でCASE句とか使ったりしてます。。。。

あのCSV作ったやつはキーボード触ろうとすると手のひらが痒くて文字を打てなくなる呪いにでも掛かって欲しい。。。

しかし自作でパースするような実装したらとんでもない量の実装になりそうだけど現場的にはそっちの方が頑張ってる感出せるのもヤバイところではあるなぁ

Discussion