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 スクリプトが終了しないのは`{....}