Path: sran265!katsu From: katsu@sran14.sra.co.jp (Katsuhiro Watanabe) Newsgroups: fj.lang.misc Subject: perl as login shell (was Re: awk vs perl) Message-ID: Date: 9 Dec 91 05:48:23 GMT References: <1991Dec4.183715.12866@InterTech.COM> Sender: news@sran265.sra.co.jp Distribution: fj Organization: Software Research Associates, Inc.,Japan Lines: 135 In-reply-to: utashiro@InterTech.COM's message of 4 Dec 91 18:37:15 GMT 記事 <1991Dec4.183715.12866@InterTech.COM> で utashiro@InterTech.COM (Kazumasa Utashiro) さんいはく > インタプリタと銘打つからには、やはりインタラクティ > ブに使えて欲しい。そういう意味でいうと perl のインタプリタは > > perl -de 1  最近、何日間か perl -d をログインシェルにして使ってみたことが ありました。結構面白かったので、その時のことを思い出して報告します。  Larry Wall さんも Tom Christiansen さんも、comp.lang.perl 等で 「perl はシェルではない。むしろ awk に近い」という意味のことを 言っているのですが、perl の会話的利用の可能性を探るために 敢えてやってみました。 [背景と動機]  perl -d は perl の式や文を直接打ち込んで評価させられるし、 history も alias もあるから、シェルとして使えるかも知れない。 (これを試した頃は perl のバージョンが 4.0 になって間もない 頃だったと思います。OS は NEWS OS 4.1C です。) [準備] (1)$ENV{'HOME'}/bin/perlsh (心の準備として、ホームディレクトリを 「~」で表す習慣もこの時点で捨てる。今や「~」は negation である。) という名前のファイルに以下のような内容を書き込んで実行許可を立てる。 このファイルが「シェル」ということになる。 #!/usr/local/bin/perl require "getopt.pl"; &Getopt('c'); if ($opt_c) { if ($opt_c =~ /^echo\s/) { print eval "\"$'\""; } else { eval $opt_c; } } else { exec '/usr/local/bin/perl -de 1'; }  シェルというものは、色々なプログラムから -c スイッチ付で呼び出される ことが多いので、-c の解釈だけはするようにする。また、-c 'echo ...' の 形でメタキャラクターの解釈をさせるコマンドがある(例えば vi など)が、 echo なんていう perl の命令はないので、仕方なくこれを特別扱いする。 (vi の中から「:e $ENV{'HOME'}/foo」のようなことができるように、 eval に渡す文字列を quote してあることに注意。)  -c がなければ perl のデバッガーを立ちあげる。 (2)$ENV{'HOME'}/.perldb を例えば以下のようにする。これは、.cshrc や .profile に相当する。 1 # 2 $home=$ENV{'HOME'}; 3 4 $ENV{'PATH'}=join(':',( 5 "$home/bin", (ここにパスを並べる。省略) 11 "/usr/ucb", "/usr/bin", "/bin", 12 "." 13 )); 14 $ENV{'SHELL'}="$home/bin/perlsh"; 15 $ENV{'ESHELL'}="$home/bin/perlsh"; 16 $ENV{'JSERVER'}="sran265"; 17 $ENV{'PRINTER'}="slbp9"; 18 19 umask(022); 20 21 $DB'alias{'@'} = 's/^@(.*)/system("$1")/'; 22 $DB'alias{'ls'} = 's/^ls(.*)/system("ls -F $1")/'; 23 24 $DB'alias{'c'} = 's/.*//'; 25 $DB'alias{'T'} = 's/.*//'; 26 $DB'alias{'n'} = 's/.*//'; 27 $DB'alias{'r'} = 's/.*//'; 28 $DB'alias{'s'} = 's/.*//'; 29 30 if ($ENV{'TERM'} eq "network") { 31 $ENV{'TERM'}="vt100"; 32 } 33 system("tset -n -e^H -k^U"); 34 system("stty sjis");  純粋な perldb では、/bin/ls を動かすのにも system("ls") とタイプ しなければならない。そこで 21,22 行目で最小限の alias を定義した。 system 関数の alias は ! にしたい所だが、history と衝突する。 24-28 行目では、デバッグ対象の「1;」というプログラムを走らせて 終了させてしまってログアウトすることのないように、元のコマンドを 無効にしている。  30 行目以降は少しいい加減だが端末設定である。  なるべく alias に頼らないで行こうとしたが、私はどうしても ls -l が できずに(stat の順番が覚えられない)上では alias を入れてしまった。 (しかも、system を呼ぶという最悪の形式で。)  単に ls するだけならば /bin/ls を起動するより、p(rint) join(' ', <*>) 等の方がよさそうである。 (3)super user になって、/etc/shells に perlsh を登録し、chsh する。 [問題点、使ってみて気付いた点など] ・tset -s には perl のスクリプトを出す機能はないので、環境によっては 困る場合があるかも知れない。 ・suspend できない。 ・プロンプトが変えられない。 ・system 関数の外でパイプを構成するのは難しい。(pipe を使って 自分でつなぐ??)しかしこれが必要なことは一度もなかった。 ・「goto foo」などとすると、bad label となってログアウトしてしまう。 (他にも似たようなものがいろいろあると思われる。) ・上の alias のやり方は完全でない。例えば「@ echo ""」が syntax error になる。(うまいやり方を知っている人は教えて下さい。) ・$ENV{'HOME'}/.perldb には、関数定義を含めて perl のプログラムが 何でも書けるので、機能の追加は容易であろう。 ・コマンドを呼び出すのに普通のシェルのようにコマンド名を打つだけで 済まないところがいらだたしい。 ・vi の ! コマンド、Emacs の shell-command-on-region などとの 組合せでは、結構 perl の強力さを味わうことができる。 ・pwd.pl を会話的に require する機会が何回かあった。毎回問題と なったのは、pwd.pl は染みついていても、初期化のために呼び出さねば ならない関数名の方は大抵忘れてしまっていることだった。 [結論] ・やはり perl -d はシェルではない。(わたしは4日目でやめました。)  perl freak の人なら、一回やってみて損はないと思います。  X を立ちあげた時など、沢山のターミナルエミュレーターで perl -d が 動いているのを見ると、ちょっと「おたく」になった気分になれます。 (当然 emacs のシェルモードでも perl -d が動いている訳です。)  上の方法で、perl を勉強したい人を「perl を使わなければ何もできない」 という背水の陣の状態に追い込んでしまうというのではどうでしょう。 「perl hacker 養成ギプス」とか称して :-) ----____----____ 渡邊克宏 SRAソフトウェア工学研究所