shell script 技法2

プログラミング言語の設計の美しさを考えるとき、全ての構文が 一貫して式として評価できるかという観点がある。 かつてのプログラミング言語では一つの分単位は「命令」として 解釈されて、それが単一で登場するだけで他に利用できなかったのだが、 最近のプログラミング言語では「式」としての意味を持つので、

a=b=c=0;

という風に書ける。c=0 が「代入」という「命令」的な意味だけで なく、結果としての0という値を持つ「式」となるので、上記のような多重代入 が可能となる。昔のBASICではこんなことはできない。無駄が無い。

ところが全てが「式」となりそうな、C言語でもこれは不完全で、 制御構造は式になり得ない。つまり制御構造は単なる構文であって 「値」を持たせることができない。このへんがわし的に美しくないと感じるとこ ろ。

Display, "even number" if x can be divided by 2 otherwise "odd number"

なんていう規則。これは、

xが2で割り切れるなら「偶数です」と、そうでなければ「奇数です」と表示する

のように日本語でもちゃんと書けるのにCでは等価に書けない。

if (x%2 == 0) {
  puts("偶数です");
} else {
  puts("奇数です");
}

何が違うかというと、元の文では Display という動詞が一回だけ登場してい たのに、Cだとputsを2回も書かなきゃならん。ダサイ(末尾註)。 Lispならこうだ。

(message (if (= (% x 2) 0) "偶数です" "奇数です"))

もちろん今一番イケてる言語Rubyでもばっちりだ。

p (if x % 2 == 2 then "偶数です" else "奇数です" end)

ifだろうがwhileだろうが、しっかりと 値を返してくれるので、かなり処理を簡潔に書ける。

さて、本題。

なんと /bin/sh もこのような一貫性を持つ。全ての構文が等しく 「コマンド」として利用できるのだ。1/31の メモで、コマンドの出力パイプの先に while read line なんての を書けたことからも分かるように、shにおいては制御構造ブロックも通常のコマ ンドのように利用できる。

まずヘッダを出力し、その後の本文については、 もし、$conv が1なら nkf した結果を、そうでなければ そのままcatしたものを Mail で送る。

という処理を考えよう。馬鹿で有名なcshではこうしか書けない。

if ( $conv == 1 ) then
  (cat header; nkf somefile) | Mail -s hoge someone@some.domain
else
  (cat header; cat somefile) | Mail -s hoge someone@some.domain
endif

shではこう書ける。

(cat header
 if [ x"$conv" = x"1" ]; then
  nkf somefile
 else
  cat somefile
 fi ) | Mail -s hoge someone@some.domain

この例だと二つの場合分けに共通の処理 cat header が ものすごく小さいからあまり差を感じないが、複雑な処理では共通部分もそれな りに大きくなる。shだと関数も定義できるからさらにプログラムの見通しは 良くできる。

逆にこんな風にも書ける。「grep hogehoge access_log した結果に対し、 $head が 1 なら先頭を、そうでなければ末尾を見せる。

grep hogehoge access_log | if [ x"$head" = x"1" ]; then
			     head
			   else
			     tail
			   fi

おお、美しい。すごいなshって。噛めば噛む程味が出る。Unixの歴史と ほぼ同じだから、Cと同時に出たインタプリタでありながらこの美しい設計。 知れば知る程ほれぼれ。


註: Cだと x ? y : z を使えば条件分岐に 値を持たせられる。が、これもifの代わりになるだけで、 たとえば switch〜case のようなもっと複雑な制御構造全体に値を 持たせることはできない。LispもRubyもどんな制御構造であれしっかり 値を持つ。shならどんな制御構造でもそれ全体が一つのコマンドのように 機能する(と思う)。


ftpsv1.u-aizu.ac.jp

このページを見てもらえるのはうれしいんだけど、、 ftpsv1.u-aizu.ac.jp からのアクセス、一番はげしいときは5秒に1度という 頻度で連続20アクセスがある。いくらなんでもこのメモを5秒に一度のペースで 更新することはできないので、せめて2〜3時間に一度のペースに落として もらえないっすかね。lily.fan.gr.jp というホストも1時間に1度だけど。 1日に1ページしか書かんぞな。

こういう風に書いて、もしアクセスのペースが変わらないとしたら、 自動アクセスはするけど読んでもらえてないって事だな。いとかなし。


Generated with mkdiary.rb
yuuji@example.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]