http:index.html
" rc - the Plan9 shell -" -- rc(1)http:rc3.html
" Unix port of rc " -- rc3
a='alice bob'
b=(alice bob)
alice bob
term% ls $a ls: alice bob: file does not exist term% ls $b alice bob term%
ls $a
ls 'alice bob'
ls $b
ls (alice bob)
ls alice bob
Plan9 のメールアドレスの表現は UUCP 形式である。そこで
s='ar.aichi-u.ac.jp!alice'
*.aichi-u.ac.jp
switch($s){ case *.aichi-u.ac.jp!* ifs=! t=`{echo -n $s} echo Welcome $t(2) case * echo Denied }
ifs='!' t=`{echo -n $s} { switch($t(1)){ case *.aichi-u.ac.jp echo Welcome $t(2) case * echo Denied }}
ifs='!' a=`{echo -n $s} { ... }
ifs='!' a=`{echo -n $s} ...
と書いたならば ifs の値が変化するから注意しよう。
何故なら、変数への代入が局所的であるには、その後にコマンドが必要だからである。
a=`{echo -n $s}
rc はマッチした場合には *
の部分のデータを内部では見つけているはずである。
その結果を参照する機能を提供していれば、もっとエレガントな書き方ができたであろう。(bash は rc よりこの点では強力である)
しかしながら rc の開発者はそのようなニーズを認めなかったに違いない。
筆者もこれで困っていない。(強力な処理が必なら sed を使用する)
Cのプログラムだとオプションやフラグの扱いは柔軟である。例えば
usage: foo [-x] [-p pattern] arg ...
foo -x -p abc a1 a2
foo -xpabc a1 a2
#!/bin/rc usage='usage: foo [-x] [-p pattern] file ...' while(~ $1 -*){ switch($1){ case -x echo $1 shift case -[x]* # set of flags *=(`{echo $1 | sed 's/^(..)(.*)/\1 -\2/'} $*(2-)) case -p echo $1 shift echo $1 shift case -[p]* # set of options followed by something *=(`{echo $1 | sed 's/^(..)(.*)/\1 \2/'} $*(2-)) case -* echo $usage exit usage } } while(~ $1 ?*){ echo $1 shift }これは期待通りの動作をする。
#!/bin/rc rfork e usage='usage: opts [-x] [-p pattern] file ...' flags='x' opts='p' flag=() opt=() while(~ $1 -*){ switch($1){ case -[$flags] flag=($flag $1) shift case -[$flags]* # set of flags *=(`{echo $1 | sed 's/^(..)(.*)/\1 -\2/'} $*(2-)) case -[$opts] o=`{echo $1 | sed 's/^-(.*)/\1opt/'} #echo $o opt=($opt $o) shift $o=$1 shift case -[$opts]* # set of options followed by a string *=(`{echo $1 | sed 's/^(..)(.*)/\1 \2/'} $*(2-)) case -* echo $usage exit usage } } for(f in $flag) echo $f for(o in $opt) echo $o $$o while(~ $1 ?*){ echo $1 shift }
qsparse
と言う名称である。)qsparse
は $QUERY_STRING
を読み取り、その結果を環境変数に落とす。$QUERY_STRING
がname=alice&age=18
qsparse $QUERY_STRING
QS_name
と QS_age
に各々 'alice
' と '18
' が納められるように設計されている。$QS_name
も $QS_age
も値を持たない。まだシェル変数になっていないからである。これらをシェル変数にするにはQS_name=`{cat /env/QS_name} QS_age=`{cat /env/QS_age}
cd /env; for(a in QS_*) $a=`{cat $a}
ところで UNIX の場合にはどうであろうか?
UNIX においては環境変数は子プロセスに引き継ぐ事はできるが、親プロセスに渡す事はできない。すなわち qsparse
のような QUERY_STRING
を解析するツールを作っても何の役にも立たないのである。
Bash ではループに対する break
を持っているが Rc は持たない。ではどうするか?
a=`{for( i in doc src tmp) test -r $i && echo $i && exit} echo $aこれを実行するとカレントディレクトリに
doc
, src
, tmp
の何れかが見つかった時に for
ループから抜け出す。多くの場合には抜け出した理由を知りたいのであるから、これで良し、break
は要らないと考えたのであろう。なお、exit
によって Rc スクリプトが終了しないのは`{....}