シェルスクリプトの実力を再検証する。
この記事は、Tipsというよりはむしろシェルスクリプトの実力を見直そうよ、という内容の記事だ。コードを詳しく見ればその中にはいくつかTipsが詰まっているかもしれないが……。
それよりも、シェルスクリプトの処理速度や機能を再認識してもらえればと思う。
ネット通販によくあるアレくらい、/bin/shでだって作れるもん!
シェルスクリプトの実力を示すべく、ネット通販の注文画面なんかでよく見かける 「郵便番号から住所を補完するボタン」 をシェルスクリプトで実装してみた。
動作デモとソース
デモは、 こちら 。ソース一式は、 GitHub上 に置いておいた。
デモ機はIntel Core2Quad Q9450 2.66GHzの1コアだけを使ったVPSで、今どきのライトな部類に入るマシンだと思う。この上で、 約14万行(レコード)=地域名12万行+事業所名2万行 ある郵便番号データから目的のデータを検索している(デモページの一番左にあるボタンを押した場合)が……、実感できる速さはいかがなものだろうか?
ちなみに、デモページの右二つのボタンはオマケである。よそのWeb APIをサーバーサイドで叩いて外部サイトに検索してもらい、結果を表示しているだけだ。だが、結果はJSONやXMLテキストで渡ってくるので、 シェルスクリプトでもJSONやXMLをパースできるよ という意図を込めて設置している。
簡単な構造解説
デモを試したらソースも見てもらいたい。クライアントサイドのプログラムは何の変哲もないJavaScriptなので割愛するが、サーバーサイドのプログラムは次の3種類から構成されている。
1.郵便番号辞書作成mkzipdic_kenall.sh
, mkzipdic_jigyosyo.sh
data
ディレクトリーの中にあるシェルスクリプト。これは、日本郵便のサイトから、Zip圧縮されたCSV形式の郵便番号データをダウンロードしてきて、その中から必要な列(郵便番号、都道府県名、市区町村名、町名)だけを取り出して辞書データファイル(サンプル(地域名用),サンプル(事業所用))を作るというもの。
コイツはCGIではなくcronで、毎晩でも毎時間でも実行させるように仕掛けておけばいい。え、「頻繁に実行したら負荷がかかるだろ!」って?大丈夫、HEADメソッドで事前にCSVデータのタイムスタンプを見比べ、新しいものが出てなければ作らないようにしてるから心配なし。
ちなみに、CSVのパースは後述の自作コマンドで行っている。(もちろんシェルスクリプト+UNIX標準コマンド製)
2.住所検索CGIzip2addr.ajax.cgi
public_html
ディレクトリーの中にあるシェルスクリプト。上記のmkzipdic.sh
で作成した辞書ファイルからCGI経由で指定された郵便番号に対応する住所をJSON形式にしてクライアントに返す。
ちなみにzip2addr_jsonapi.ajax.cgi
とzip2addr_xmlapi.ajax.cgi
は、先に記したとおり、よそのWeb APIに検索を任せるオマケである。
3.CSV、JSON、XMLパーサーparsr*.sh
commands
ディレクトリーの中にあるシェルスクリプト。役割は題名のとおりだ。コイツらを通すと、CSVやJSONやXMLデータの欲しいところがAWK
やgrep
等で簡単に取り出せるようになって超便利。
先に記したとおり、これらももちろんシェルスクリプト+UNIX標準コマンドで作られている。
実は「速い!」「色々できる!」シェルスクリプト
この記事で結局私が訴えたいのは、この見出しに書いたことである。
シェルスクリプトなんて遅いから使えないよ
と思っているアナタ。いやいや「ちょっと待ったー!」と言いたい。
シェルスクリプトはグルー言語。シェルスクリプト自身でこなそうとせずに、コマンドを呼んでそれらに任せればいいのだ。コマンドを呼べば、シェルスクリプトはその後コマンドの終了を待っているだけ。UNIX標準コマンドたちはC言語で書かれているため、それらを駆使するシェルスクリプトなら、殆どCプログラムの速さで動くことになる。
また、データの持たせ方も工夫次第。郵便番号はたかだか14万行だから1ファイルでよかったが、もし100万行、1000万行のデータだったら……と思うかもしれない。そうなったら、例えば郵便番号の前3桁ごとにファイル分割して持つまで。頭の3桁の検索は、OSがファイルシステムのハッシュテーブルを使って高速に行ってくれるのでシェルプログラマーが自力で高速検索アルゴリズムを組む必要は、たぶんまだ無い。
シェルスクリプトは他言語みたいに豊富なライブラリーないし、大したことできないよ
と思っているアナタ。いやいや、たぶんアナタの想像以上にいろんなことできるはず。
例えばこのデモでCSVやJSON、XMLテキストの解析をさせているが確かにそんなことをしてくれるコマンドは無かった。だが、シェルスクリプトを使って自作した。中身(CSV用、JSON用、XML用)を見てもらいたい。シェルスクリプトとsed
やAWK
やgrep
、tr
など、どれも見慣れた構文やコマンドでできている。 難しいことも、簡単なことの組み合わせで実現できるのがシェルスクリプトの強み なのだ。(マイクガンカーズのUNIX哲学定理6,7あたり)
「じゃあ、Webアクセスは?」……それもこのデモで示したとおり、curl
を使えばOK。「メールは?」……それは/usr/sbin/sendmail
を使えば大丈夫、受信ならfetchmail
コマンドとか。「でも、本格的なRDB操作はさすがに無理でしょ」……いやいや、 POSIX標準コマンドでjoin
ってのがあって これとかsort
とかAWK
とか使えば、テキストファイルでも相当本格的な操作が可能。
おかげでネット通販によくあるコレだけじゃなくて、ネット通販サイトそのものを作ったりしちゃったりなんかしちゃったりして