著作一覧 |
なんとなく買ってしまったFlameだが(理由はいろいろあるけど)、Firefox OS 1.3ではさすがに意味がないので、2.1にしてみた。
が、どうもCygwinの人間が出したPRを精査せずに取り込んだらしくて、OSXでアップデートしようとすると/cygdrive/c/tempが見つからないというようなエラーとなる。
最初、普通にWindowsを使おうと思ったのだが、Flameガイドからリンクされているツール(shallow flash script)が#!/bin/bashだったから、いちいちバッチファイルなり他のスクリプトなりに変換するのも面倒なのでOSXを使うことにしたのだった。
そうしたら、上記のエラーとなる。なぜだ。
で、スクリプトを見ると(ということをしたくないからOSXを使ったのだが)
if [[ `uname`="CYGWIN"* ]]; then cp -r $TMP_DIR /cygdrive/c/tmp fi &&
みたいな行がある。しょうがないので直してPRしようと思ったら、おれがエラーになっている間に修正PRが出ていた(で、今は直っている)。
このifの後ろの[]
が、一番、プログラミング言語とシェルスクリプトの違いが出ている点だと思う。
そして大抵のシェルプログラミングの本だと、必ず空白を入れろというような説明になっている。そのため(理屈がないし、不自然だから)必ずバグの原因となる。
その点でなるほどと納得したのが、シェルスクリプト高速開発手法入門の説明だった。
B00LBPGFJSシェルのifが条件式として取るのは、シェルコマンド(内部コマンド含む)で、戻り値が0なら真とみなす。
コマンドなので、当然[
はコマンドであり、[
がコマンドということは条件式はそのコマンドに対する引数となる。良く使う構文は4引数で[ 左項 演算子 右項 ]
で、Unixのコマンドということはargvに格納されるのだから、空白で区切るのは当然のことなのだ。
$ which [ /usr/bin/[ $さらに
$ type -a [ [ はシェル組み込み関数です [ は /usr/bin/[ です [ は /usr/bin/X11/[ です $ type -a [[ [[ はシェルの予約語です $
([[
はbashのビルトインコマンド(shには無いと思った)なので上の"CYGWIN"*のようなグロッビングがサポートされているので、あまり考えずに常に[[
を使っても良いように思う)
$ uname Linux $ [ `uname` = "Lin"* ] $ echo $? 1 $ [[ `uname` = "Lin"* ]] $ echo $? 0 $
$a=32 $echo $a 32 $b = 48 b: command not found $
というのも当然といえば当然だが、実に気に食わない動きだ。
コマンドと空白で区切った引数で記述できる=最小の実装の組み合わせで効果を得るというそれがUnixだといえることではあるけれど、そろそろこれやめにして、プログラミング言語のREPLにならんものかなぁ。irbでObjectの未定義メソッドはなんでもかんでもsystemに与えるようにすればそれなりに使えるかな?
ジェズイットを見習え |
tclのreplがデフォルトで、トップレベルで未定義コマンドが出てきたらexecを試みるようになってた覚えが。でもシェル代替として流行るところまではいかなかったですね。
tclだからありがたみが乏しいからなのか、UnixのDRY主義(いずれにしても最終的にはコマンドを組み合わせることになる)が原因なのか興味深いですね。シェル高速開発の人たちだったら、パイプで繋げば並行処理になるから効率的だとか言いそう(理には適っている)。