この記事はPOSIX原理主義Advent Calendar 2016の2日目の記事です。
今日のテーマは、昨日の記事でも紹介されていたPOSIX原理主義の書籍の話です。いきなりですが、商品の購入ボタンを置いておきます。
続きを読む
2016年の夏コミで発行したShell Scriptライトクックブック2014-2016を通販してます
2016年8月14日 発行(コミケ90 3日目)
頒布価格:1500円
ページが増えて232Pに
(Safariをお使いの方はコチラで注文)
詳細は目次をご覧ください。と済ませるのもあんまりなので、ポイントを記します。
そもそも改訂は第3版でおしまいと言っていたのですが改訂しました(スミマセン)。というのも、Bash on Ubuntu on Windowsという大革命が起きたからです。POSIX原理主義がWindowsでも通用する時代が到来したとなったらそれをサポートすべく対応しないわけにはいかない、というわけでBash on Ubuntu on Windowsに対応した内容にしました。
併せてレシピも追加しましたが、一番の目玉はTwitterに関するレシピ。シェルスクリプトからTwitter APIを操作して、投稿、検索、DM送受信などの日常使いを実現する方法を追加しました。
つまりこれらは、Bash on Ubuntu on Windowsでも動くTwitterアプリが作れるということを意味します。
先程紹介したTwitterレシピをはじめ、合計15のレシピを追加しました。5章の「どの環境でも動くシェルスクリプトを書く」の内容をより完璧にしたり、他に大きなものとしては、1秒未満sleepをいかにしてPOSIXの範囲で実現するかなどを解説しています。たぶんこれはコロンブスの卵的に目から鱗なはずです。
POSIXの範囲では不可能な処理を行うためにはどうしてもPOSIX外のコマンドを利用しなければなりませんが、従来は「やむを得ないので、最低限にとどめる」という見解であり、理論的に不完全でした。第4版ではこれを修正、「交換可能性の担保」という考え方を導入することで、理論的な曖昧さを解消しました。
また、東京メトロのコンテストから1年半経過し、一体どれだけの応募作品が今でも動いているのかの実態調査レポートも掲載しました。POSIX原理主義を用いないソフトウェアの保存の利かなさが露呈する結果になりました。(こんな結果で東京五輪観光客向けのアプリ開発促進計画は大丈夫なんでしょうか?)
通常のコミケではないし……、遠いし……、行けないよ。という方もご安心を。通販やってます。この通販のためのプログラムは、本書で紹介したレシピをふんだんに活用し、シェルスクリプトで作られたものです。本書レシピの実力の程を確認するためにも、このサイトの通販を是非ご利用ください。(Safari等、このサイトのカゴ入れボタンがうまく機能しない方はコチラへ)
書籍「すべてのUNIXで20年動くプログラムはどう書くべきか」を著者の通販サイト(ココのサイト)で購入されるお客様に、ささやかながら値引きを致します。
とはいっても商業本を値引きすることはできない決まりなので、元になった同人誌をセットで購入される方に、その同人誌の方を400円値引きします。
他の書店には絶対マネできないこの企画。是非下のボタンを2つともポチしてください。(Safariの方は本店でポチ!)
商業版カゴ入れボタン | 同人版カゴ入れボタン |
---|---|
以前、あのジャパネットの高田社長が「ショッピングはエンターテインメントです」と言っていた。「分割金利手数料は店が負担」の第一人者だし、ハプニング覚悟で生放送を止めないし、高田社長は経営を引退しても未だに出演は続けている。
それらはまさに、エンターテインメントだという前提があるからであって、ジャパネットたかたはメーカーが作った作品(=製品)を売りながら、自分達が考案したショウ(=実演)や値引き(=分割金利手数料負担然り)という作品を売っているのだ。
つまり「値引き」とは店の作品の一つである。作品であるということは、値引きの仕方にもオリジナリティーがなくてはならない。客はオリジナリティーを感じるから、例え値引き額がさほどでなくても、その店を選ぶ。(実際、ジャパネットの価格も価格.comで見つかる最安店には敵わないことが多い。それでも売れる)
そうすると「なるほど、独自の値引き制度を考案するのも一つの手なのか!よし、やろう」と思う。ところが、多くのネットショップ店主にとってはそれが難しい。なぜなら、ネットショップ上で値引きを実施したければ、ショッピングカートプログラムにやらせなければならない。でも店主は基本的にプログラマーではないので、ショッピングカートで値引き販売をしたければ既製のものから選ぶしかない。結局それは店独自の「作品」ではない。
WordPressといったCMSなど、ページデザイン(店の内装)の制作にはある程度店独自にオリジナリティーを表現させるプログラムはあるのに、なぜ値引き制度という分野ではオリジナリティーを表現させるプログラムがないのか!
このような問題点に気付いたので私は自前のショッピングカートプログラムに値引き機能を実装してみた。もちろん、既製の値引き機能を作るのが目的ではない。導入する店主が独自の値引き企画を導入できる仕組みだ。
細かい話はヌキにして、どうやったかだけを記そうと思う。ちなみに、うちの自作ショッピングカートはシェルスクリプトで書かれている。
値引き機能を入れ込む対象となるのは、買い物明細を生成するプログラムである。しかし、これを下手いじるとシステムそのものが復旧不可能なほどに壊れてしまうという問題がある。
そこで、開発者と店主がいじるべき領域の違いを明確化すべく、店主がいじるべきプログラムファイルは外出しし("$Homedir/CONFIG"というディレクトリーの中に"DISCOUNT_RULES.SHLIB"という名前で置くこととし)、存在すればインクルード(".":sourceコマンド)するようにした。→冒頭部分
上記のコードの後半部分は、明細テキストデータを生成している箇所だ。joinやawkをパイプで繋ぐといういかにもシェルスクリプトらしいコードである。
このコードの中盤に"DISCOUNT_BEFORE_CALCULATING_TAX"という謎のコマンドが出てくる。これが(消費税計算前に)値引きを行うためのプログラム(後述)なのだが、じつは外部コマンドではなくてシェル関数である。typeコマンドによってその存在を確かめてから、存在すれば実行し(パイプで通し)、存在しなければcatコマンドで到来データをそのまま通過させるというロジックだ。
if文ごとパイプに通せるのがいかにもシェルスクリプトでしょ?
明細生成プログラム本体はフックを入れただけなので、値引きを実行するプログラム本体は別にある。店主は、独自に考案した値引き企画を、この部分でシェルスクリプトという表現手段を用いて表現する。
店主は、値引きを企画したいのであれば $Homedir/CONFIG/DISCOUNT_RULES.SHLIB という名のファイルを用意し、DISCOUNT_BEFORE_CALCULATING_TAXというシェル関数を書く。
今回は、商業本(商品ID=pfb)と同人本(商品ID=ssr2)を同時購入した筋金入りのPOSIX原理主義者に向けた割り引きだが、それをプログラミングしたものが次のシェルスクリプトだ。
実体はAWKのコードである。それがシェル関数でラッピングされているに過ぎない。
標準入力から、冒頭のコメントにある通りの仕様でカゴに入っている商品明細データが渡ってくるのでそれを標準出力へと素通りさせつつ、そのうしろに今回の値引きルールに基づく値引き項目を追加して標準出力へ送るのである。出力時のデータフォーマットも、冒頭に記されたコメントに従う。
上記の解説はプログラミングに慣れた人にとってはさほど難しい話ではない。では、そうではない純粋な商売人にはどうだろうか?
確かに上記のようにして値引き実施コードを本体から切り離したものの、きちんと書かなければ本体も動かなくなるわけで完全に安全になったとは到底言えない。
しかし、ネットショップの内装(デザイン)を弄るためにHTMLやCMSを覚えことのがある程度受け入れられているのだから、その程度にまで敷居を下げさえすればよいと思うし、またできるはずだ。
それができなければ、個人のネットショップなど大手に潰されてしまう。
「総務部総務課山口六平太」というマンガ知ってますか? 自動車会社に勤めるサラリーマンが主人公の話ですけど、日本の自動車メーカーなのに社用車がベンツというのがネタだったのです。
「車売ってる会社なのに、社長はベンツに乗ってんのかよ!」って、誰しもツッコミたくなりますよね。まぁ、あれは大日自動車株式会社という架空の会社ですけど、じゃあ実在の日本の自動車会社はどうかというと、あれ?いすゞ!。……まぁ、今や乗用車は作っていないですからね。(そもそも情報古いですし)
メーカー | 氏名 | 社長車 | 私用車 |
---|---|---|---|
トヨタ | 張 富士夫 | センチュリー、クラウン | プログレ、コロナ |
ホンダ | 吉野 浩行 | レジェンド | ラグレイト |
日産 | カルロス・ゴーン | プレジデント | セドリック、エルグランド |
マツダ | マーク・フィールズ | センティア | RX-7 |
三菱 | 園部 考 | ディグニィディ | ギャランVR-4 |
ダイハツ | 山田 隆哉 | アルティス | アルティス |
スバル | 竹中 恭二 | レガシィB4 | レガシィB4 |
スズキ | 戸田 昌男 | カルタスセダン | なし |
いすゞ | 井田 義則 | キャデラックコンコース | ビックホーン、アスカ |
自動車会社にとって社長の車といったら社の象徴なので、それが他社製だったら身も蓋もない話ですよね。
ところが、コンピューター言語においては、そんな身も蓋もない話が、誰にもツッコミを受けることなく行われてきました。シェルスクリプトのアプリ開発言語としての実用性を謳う本の通販サイトがPHPとか……、そりゃないでしょ。
いゃベンツだってPHPだっていい車や言語ですし、それに別に売るなってわけじゃないですよ。でも著者が、他言語で作られた販売サイトを宣伝する(しかできない)って何のジョークだ!と思うのです。
でも、彼の会社の社用車がベンツだったのは初期の話。念願かなって今ではサザンという自社製のセダンになっています。
つい昨日、念願かなって、シェルスクリプト製になりました。いや、今までも既に販売サイト自体はあったんですけど、今回めでたく商業本を私(著者)手作りのシェルスクリプト製販売サイトで取り扱えることになりました。C&R研究所さん、ありがとう!こういう柔軟さは大手には簡単には真似できませんね。
というわけでカゴ入れボタンを貼っておきますね。
リアル リッチ・ミカン[著]、USP研究所[監]、C&R研究所[発行]
2015年7月24日 発売
本体2,500+税200円
A5版 2色刷 0x100頁
(Safariをお使いの方はコチラ)このサイト(はてなブログ)自体は、まず間違いなくシェルスクリプト製ではないでしょうけど、ショッピングカートのパーツ(カゴ入れ&レジボタン)はシェルスクリプト製ですからね。このショッピングカートプログラムの特長は、例え他言語CMSで作られたページでもショッピングサイトと化すことができるという点なのです。
だから、人気の出たブログ上でブログ主が商売も始めたいと思ってもわざわざ引っ越す必要がなくなるのです。便利でしょ?
ちなみに、本家の商品ページは現在、ウザい宣伝欄がくっついています(笑)。これもこのショッピングカートプログラムが本質的にCMSを選ばないから簡単にできる技。
前回の冬コミとコミスペ6で頒布したPOSIX原理主義同人誌が、商業本になって本屋に並ぶことになりました。
リアル リッチ・ミカン[著]、USP研究所[監]、C&R研究所[発行]
2015年7月24日 発売
本体2,500+税200円
A5版 2色刷 0x100頁
(Safariをお使いの方はコチラ?)
どれくらい硬派かというと「bashはbashという言語であって、シェルスクリプトを語るに値せず」というくらい硬派です。そう言うと反感を覚える人もいるでしょうが、bash独自拡張機能を利用しておきながら冒頭に平気で「#! /bin/sh」を書く人に対して反感を覚えるという人なら、きっと仲良くなれるはずです。
Bourne Shellを至上とし、もちろんGNUコマンド等も使わず(使ってもいいけど独自拡張機能は一切使わず)、極力POSIXの範囲でプログラムを組みます。それなのに、こーーんなことがちゃんとできます。
実用性があることはわかったとして、なぜわざわざPOSIX原理主義にこだわるのか?それは「どのUNIXに持っていってもそのまま動く」、「10年20年の長きに渡ってそのまま動く」という、超可搬性・超可用性を追求するためです。
世の中、「速い」「簡単」を謳う言語やライブラリー、フレームワークで溢れてます。コストを削減せよ!業務を効率化せよ!とウンザリするほど言われているとそういうものに飛びつきたくなります。しかし飛びついたらどうなるか……。待ち構えているのはメンテナンス地獄です。
とかそんなのばっかり。本当にコスト削減&業務効率化は図られているのかと、疑いたくなります。
一方でPOSIX原理主義を遵守すると、こういう目にはほとんど遭わずに済むようになります。なにせPOSIXは枯れているからです。枯れているゆえに殆ど機能追加はありませんし、ましてや機能の廃止など殆どありません。とは言え「OSに脆弱性が見つかったらメンテしないわけには行かないだろ」と思うかもしれません。いや大丈夫です、どのUNIX系OS開発団体もPOSIX規格だけは遵守しようとしますから、POSIXの範囲で組んだプログラムしかないから、何も恐れることなくOSのバージョンアップができます。また、OSを乗り換えることもできます。しかもシェルスクリプト+テキストファイルでシステム組んでいれば、コピーするだけで乗り換え完了です。
さようなら、デプロイ沼とメンテナンス地獄……。
冒頭でも出てきた同人誌というのは、これです。あ、同人誌ですからね、コレ。某出版社のページ探しても見つかりませんよ。ちなみに、このイラストはウチのサークルで手描きしたものです。
内容は同じで、旧バージョン(最新版は2015/03/29版)です。ただ、今回商業本化するにあたっては、クォリティーの違いを見せつけられましたね。実物を比べてみれば明らかに商業本の方が欲しくなるデキです。
商業本と同人誌本はクォリティーの違いで棲み分けができていると思うのですが。実は、同人誌の元ネタ(つまり商業本の元ネタでもある)は、私がQiitaに書き貯めた投稿です。
中には商業本化の話が動き出してから投稿した記事もあります。先にWebに公開して、それを後から本に収録したのです。
「そんなことをしたら本が売れなくなるでしょ?」と疑問に思うかもしれませんが、私の経験上そんなことはありません。事実、この同人誌はWebに公開せずに作った同人誌(シリーズ第一弾)と同じ勢いで売れましたし、中には「Web(の記事)でいつもお世話になってまーす」と言って買いにいらしたお客さんもいました。
ですのでこの本(同人誌&商業本)には、Webで同じ記事があっても売り上げには影響しないことを実証する意味合いがあります。むしろ、Webで事前公開することによって記事のオープンβテストができるという利点さえあります。
どうでしょう、Qiitaでほぼ同じ内容が見られると知ったら購買意欲を削がれましたか?
さてさて、この本はどれだけ売れるでしょうか?内容に興味の無い方も、その結果にご注目を!
昨年末の冬コミで発行したShell Scriptライトクックブック2014、第二版をコミケットスペシャルで発売します。
2015年3月28日 発行(コミケットSP6 1日目)
頒布価格:1200円
ページが増えて154Pに
(Safariをお使いの方はコチラで注文)
詳細は目次をご覧ください。と済ませるのもあんまりなので、ポイントを記します。
シェルスクリプトを書いていると次から次へとレシピが増えますが、今回も少し増えました。例えば、Base64のエンコードとデコードです。Linux等ではBase64のコーデックたるbase64コマンドが始めから入っていて不要なレシピかもしれませんが、POSIXの範囲で実装した話を紹介しています。これによって、他の環境でも安心してBase64が扱えます。
Base64との相互変換を実現するは、バイナリーコードを扱える必要があります。ところが、AWKの変数(GNU版除く)やシェル変数(zsh除く)ではそれができません。では一体どうやってシェルスクリプトでバイナリーコードを扱うのか、という話もレシピとして追加しました。
その他、どの環境でも使えるシェルスクリプトを書くためのレシピを多数追加加筆しました。
ところで、なぜBase64を扱うレシピを追加したのか。それは、メール送信のレシピからnkfコマンドを葬り去るためです。
これまでは、UTF-8文字をSMTPサーバーが許容する7ビット文字セットであるJISコードに変換するためにnkfを利用していました。しかし、Base64エンコードをして英数字だけにしてしまえばUTF-8のまま送ることが可能になるというわけです。また、Subject:などに置く日本語文字列をBエンコード(ISO-2022-JPとBase64エンコード)するためにもnkfコマンドを利用していましたが、これもUTF-8のままBase64変換すればよいわけで、base64コマンドという車輪の再発明によってこちらからも排除することに成功しました。
さようならnkf……、他にもmktempやwhichをPOSIXの範囲で実装することに成功したため、それらに頼っていたレシピもよりPOSIX原理主義に忠実なものになりました。
完成した第二版は、3/28(土)から開催されるコミケットスペシャル6で頒布します。スペース番号は、1日目 K-58bです。
通常のコミケではないし……、遠いし……、行けないよ。という方もご安心を。通販やってます。この通販のためのプログラムは、本書で紹介したレシピをふんだんに活用し、シェルスクリプトで作られたものです。本書レシピの実力の程を確認するためにも、このサイトの通販を是非ご利用ください。(Safari等、このサイトのカゴ入れボタンがうまく機能しない方はコチラへ)
既にいろいろなところで話に上っているけど、東京メトロが「オープンデータ活用コンテスト」というのをやっている。
時刻表や駅の設備といった静的な情報はもちろん、リアルタイムの列車位置なんかも公開するという大盤振る舞い。「これで役立つアプリを作ってね」ということなのだが、じゃあ俺がシェルスクリプトで何か作ってやろうじゃないかと、いうことでパイプを駆使した活用プログラムを作ってみた。
一般的な意味の「パイパー」とは、
こういう人のことを言うらしい
というわけで作ってみたプログラム、その名は「メトロパイパー」。パイパーというと、本来は右の写真のような男の娘を意味するらしいのだが、ここでのパイパーとは「UNIXシェルのパイプを操る者」と「地下鉄のパイプ(=路線)を覗く者」という意味にしている。
各種情報はここ以外にも下記のサイトに置いておいたので参考にしてね。
まず接近情報とは何かだが、駅のホームへ行くとそこの電光掲示板に表示される、
とか
前々駅 -◆- 前駅 --- 当駅
というアレだ。
でも、あの情報がその駅に居なくても見られたら便利だよなー、とまえまえから思っていた。例えばこんなシーンはないだろうか。
という具合に、今いる駅の、先や、もっと手前の駅の接近情報、あるいは駅にいなくてもこれから行く予定の駅の接近情報ってわかれば便利でしょ。使い方は直感的にわかるように作っているつもりなので使ってみてね。
このプログラムの特徴は何と言っても、中身のほとんど全て*1がシェルスクリプト+UNIX標準コマンドで書かれているということだ。しかもUNIX哲学の思想を随所に採り入れ、パイプを多用している点だ。
そのいくつかを紹介しよう。
まずはソースコード「SHELL/VIEW_METROLOC_0.SH」を見てもらいたい。
######################################################################
# 列車ロケーション情報API呼び出しと、キャッシュ作成
# (キャッシュの有効期限が切れているならば)
######################################################################
:
# --- 有効キャッシュがなければ作る(タイムスタンプは有効期限日時に設定)
[ $cache_is_fresh -eq 0 ] && { curl -s $url | parsrj.sh > "$File_cache"; }
:
:
######################################################################
# API取得データ(列車ロケーション情報の取得)の加工
######################################################################
# --- 必要な項目・区間&方面のみに絞り込んだ在線位置マスターファイルを作る
cat "$File_cache" |
sed 's/^\$\[\([0-9]\{1,\}\)\]\.[^:]\{1,\}:/\1 /' |
awk '$2=="railDirection" {$2=1;print;} #
$2=="fromStation" {$2=2;print;} #
$2=="toStation" {$2=3;print;} #
$2=="trainType" {$2=4;print;} #
$2=="terminalStation"{$2=5;print;} #
$2=="trainOwner" {$2=6;print;}' |
sort -k1n,2n |
awk '{print $3}' |
awk 'NR%6!=0{printf("%s ",$0)} NR%6==0{print $0}' |
# 1:方面コード 2:発車駅コード 3:到着駅コード 4:種別コード 5:目的駅コード 6:車両所有業者コード
:
これは実際にAPIを叩いて値を解析しているコードの一部だ。
東京メトロの今回のオープンデータAPIはJSON-LDという形式で情報を返してくる。そこで拙作のJSONパーサー"parsrj.sh"(→解説)で、(1)値の位置、(2)値という、各行2列で構成されるテキストに変換し、それをさらにAWKを使って(1)方面コード(上り下り的なもの)、(2)発車駅コード、(3)到着駅コード、(4)種別コード、(5)目的駅コード、(6)車両所有業者コード、という6列のデータに変換している。
こうやってJSONを一旦行列指向のフォーマットに変換してしまえば、あとはgrepやAWKで絞り込んだり加工したり……と、リレーショナルデータベース的な操作が自由にできる。
「リレーショナルデータベース的な操作」と言ったからには当然JOINもできる。例えば、同じソースコード「SHELL/VIEW_METROLOC_0.SH」の下記の部分を見てもらいたい。
# --- コードを名称化し、列車存在位置から列車名を引くマスターファイルを作る
cat $Tmp-this-rw-dir-loc |
# 1:現在居る3桁駅ナンバー(3桁目は0または5で、5は中間にいることを表す) 2:種別コード
# 3:目的駅コード 4:車両所有業者コード #
sort -k2,2 |
join -1 1 -2 2 -a 2 -o 2.1,2.2,1.2,2.3,2.4 $Homedir/DATA/METRO_VOC_MST.TXT - |
sed 's/\([^. ]\{1,\}\) /\1 \1 /' |
awk '{print $1,$3,$4,$5}' |
# 1::現在居る3桁駅ナンバー(3桁目は0または5で、5は中間にいることを表す) 2:種別名
# 3:目的駅コード 4:車両所有業者コード #
sort -k3,3 |
join -1 1 -2 3 -a 2 -o 2.1,2.2,2.3,1.2,2.4 $Homedir/DATA/METRO_VOC_MST.TXT - |
sed 's/\([^. ]\{1,\}\) /\1 \1 /' |
awk '{print $1,$2,$4,$5}' |
# 1:現在居る3桁駅ナンバー(3桁目は0または5で、5は中間にいることを表す) 2:種別名
# 3:目的駅名 4:車両所有業者コード #
sort -k4,4 |
join -1 1 -2 4 -a 2 -o 2.1,2.2,2.3,2.4,1.2 $Homedir/DATA/METRO_VOC_MST.TXT - |
sed 's/\([^. ]\{1,\}\) /\1 \1 /' |
awk '{print $1,$2,$3,$5}' |
# 1:現在居る3桁駅ナンバー(3桁目は0または5で、5は中間にいることを表す) 2:種別名
# 3:目的駅名 4:車両所有業者名 |
sort -k1,1 > $Tmp-this-rw-loc
APIから送られてくる接近情報データは人間に分かりやすい名称ではなく、各種コード文字列になっている。これを人間向けにするなら、各種コードに対応する名称の記されたマスターファイルとJOINして、名称の列に置換する必要がある。
それをやっているのがこのコードだ。ここでは、種別(各停とか急行とか)、目的駅、車両所有業者を、各々コードから名称にするため、マスターファイル(METRO_VOC_MST.TXT)と3回JOINしているのがわかるだろう。
上記はデータの加工に関する話であったが、Webインターフェースを扱う部分にも特徴が表れている。
動作デモを見てきてもらえばわかるが、駅を選択する<select>タグの中身はAjaxで書いている。大抵は、Webサーバーから<option>タグに渡す名称と値をJSONなりXMLなりで受け取り、項目の数だけdocument.createElementをforループで回すことだろう。
しかし、サーバーサイドがシェルスクリプトならではの技で、<option>タグHTMLそのものをサーバー側で生成し、<select>エレメントのinnerHTMLにゴッソリ流し込むというやり方を使っている。
まず、流し込まれるHTMLテンプレート「TEMPLATE.HTML/MAIN.HTML」を見てもらいたい。中に次のような記述の箇所がある。
:
<td>
<select id="from_snum" name="from_snum" disabled="disabled" onchange="get_locinfo()">
<!-- FROM_SELECT_BOX -->
<option value="-">選んでください</option>
<!-- FROM_SNUM_LIST
<option value="%1">%1 : %2線-%3駅</option>
FROM_SNUM_LIST -->
<!-- FROM_SELECT_BOX -->
</select>
</td>
:
このHTMLファイルは当然サーバー上に置かれており、次のシェルスクリプト「CGI/GETSNUM_HTMLPART.AJAX.CGI」でこれを利用している。その一部を抜粋する。
# --- 部分HTMLのテンプレート抽出 -------------------------------------
cat "$Homedir/TEMPLATE.HTML/MAIN.HTML" |
sed -n '/FROM_SELECT_BOX/,/FROM_SELECT_BOX/p' > $Tmp-htmltmpl
# --- HTML本体を出力 -------------------------------------------------
cat "$Homedir/DATA/SNUM2RWSN_MST.TXT" |
# 1:駅ナンバー(sorted) 2:路線コード 3:路線名 4:路線駅コード
# 5:駅名 6:方面コード(方面駅でない場合は"-")
awk '{print substr($1,1,1),$0}' |
sort -k1f,1 -k2,2 |
awk '{print $2,$4,$6}' |
uniq |
# 1:駅ナンバー(sorted) 2:路線名 3:駅名 #
grep -i "^$rwletter" | # ←関係ある路線だけに絞り込んでいる
mojihame -lFROM_SNUM_LIST $Tmp-htmltmpl -
まず前述のHTMLのうち<option>タグの部分(FROM_SELECT_BOXというコメントで囲まれた区間)をsedで抽出している。その後、駅名マスターファイル(SNUM2RWSN_MST.TXT)の中に書いてある、(1)駅ナンバー、(2)路線名、(3)駅名のみをAWKなどで取り出し、mojihameというコマンドに流している。
ここで呼び出しているmojihameというは、やはりシェルスクリプトで書かれている自作コマンドなのだが、標準出力から与えられた行数だけ、先程抽出したテンプレートの<option>タグの行を複製するという処理を行っている。<option>タグの箇所には"%1"~"%3"というマクロ文字があるが、これらが標準入力から渡ってきた各列の文字列に置換される。これによって、
<!-- FROM_SELECT_BOX -->
<option value="-">選んでください</option>
<option value="C01">C01 : 千代田線-代々木上原駅</option>
<option value="C02">C02 : 千代田線-代々木公園駅</option>
<option value="C03">C03 : 千代田線-明治神宮前〈原宿〉駅</option>
:
<option value="Z14">Z14 : 半蔵門線-押上〈スカイツリー前〉駅</option>
<!-- FROM_SELECT_BOX -->
というテキストが生成されるのだ。あとは、先程言ったようにこれをAjaxでブラウザーに渡して、innerHTMLでごっそりハメ込んでもらえば完成。
実はこのプログラムは、そんな先入観を吹っ飛ばすべくして作った。
なにせこのプログラムは、curlコマンドとWebサーバー(Apache)以外は全てPOSIXの範囲で作っている。LAMPという言葉があるが、つまりMとPの部分は無し!だからLとAのある環境ならどこでも動くということだ。そしてコンパイルも不要、POSIXの範囲だからBash依存やGNU依存なども無い。さらに言うと、LとAの部分の実装は問わないので、Lの代わりはFreeBSDでも、Solarisでも構わないし、Aの代わりにnginxなどでも構わない。シェルスクリプトは高いポータビリティーを持つ、ということだ。
また、「できるのはわかるけど、フレームワーク無しに一から作ってたら時間かかるだろうが」と思うかもしれないが、それも誤りだ。このコンテスト募集開始日(2014/09/12)から、本ソフトの公開日(2014/09/16)までたった4日であることに注目すべきだ。しかも実際は1日で書いている(信じないかもしれないが)。公開日が16日なのは、ソースコードの公開が利用規約に違反しないという公式回答が15日にあったので、「それなら作るか!」と作ったのが始まりだったのだ。1日、それが信じられなくても4日で作ったというこの事実が、シェルスクリプトは短期開発でも「使える」ということを証明しているだろう。
見直した? 見直したら、そんなシェルスクリプトでとあるアプリを開発したとうネタを収録した薄い本
コミケ4日目は、はてブで本を買おう - りっちけんきゅうじょのにっき
も、よろしくね。(ちゃっかり宣伝)