STEXの/home/ohba/gnuplot 以下にあるサンプルプログラムのほとんどはperl という言語で書かれている。perl についての解説やリンクは、こちら。一般的な科学計算で用いられる FortranやC,C++が、ソースプログラムをコンパイルしてから実行する、という 二段階の手続きが必要である(コンパイラー言語)であるのに対し、perl は プログラムを書いたらすぐ実行出来る(インタープリタ言語、または、スクリ プト言語)。ただ、通常のインタープリタ言語(Basicやシェルスクリプト) が、一行ずつ翻訳しながら実行されるのに対し、perl はプログラム全体を一 旦コンパイルして中間コードを生成してから実行されるので、あまり、速度の 低下は気にならない。perlは、最近は、WEBのCGI言語として広く用いられてい る。
perlの文法は柔軟なので、最低限の記述で行いたい操作ができるが、その反面、 文法を知らない人が見ると、(特に入出力の部分などは)暗号のようなプログ ラムに見えるかもしれない。ただ、データの演算などはCやFortranと違いがあ るわけでないので、(perlの文法を知らなくても)既存のプログラムを少し変 更するだけで、行いたいデータ処理はできる。(もちろん、自分でC言語で書 いても構わないが... )
プログラムを作ったつもりなのに、そのプログラムが実行してくれないこと がある。Unix では、プログラムが実行されるためには、そのプログラム内の 処理が正しいかどうか以前に、次のふたつの条件が満たされていないといけな い。
Unix のファイルシステムでは、ディレクトリやファイル毎にアクセス権を設定出来る。 例えば(以下の例では、% はシェルのプロンプトを表し、それ以下が実際に打ち込んだコマンドである)、
で表示されるファイルで、各行の最初の rwx などの3文字の組がそれぞれ所有 者・グループ・ユーザーすべて、に対するアクセス権である。r は読み込み許 可、w は書き込み許可、xは実行許可である。- はそれが許可されていないこ とを表わす。ここのすべてのファイルは、すべてのユーザーが読むことが出来 るが、書き込み(変更)が出来るのは所有者(ohba)だけである。このうち、実 行可能なファイルは8個である。% ls -l /home/ohba/gnuplot/ total 22 -rwxr-xr-x 1 ohba wheel 986 11/ 5 11:55 aniso_vs_temp -rwxr-xr-x 1 ohba wheel 654 12/22 2000 anisotropy -rwxr-xr-x 1 ohba wheel 509 12/22 2000 area -rwxr-xr-x 1 ohba wheel 407 12/22 2000 g-factor -rwxr-xr-x 1 ohba wheel 514 12/22 2000 normal -rw-r--r-- 1 ohba wheel 48 12/22 2000 psplot -rwxr-xr-x 1 ohba wheel 350 11/ 5 12:40 raw -rwxr-xr-x 1 ohba wheel 415 12/22 2000 rawall -rw-r--r-- 1 ohba wheel 2917 12/22 2000 rf1500.txt -rw-r--r-- 1 ohba wheel 8071 12/22 2000 rf5000.txt -rw-r--r-- 1 ohba wheel 204 11/ 5 12:47 sample_dopc.txt -rwxr-xr-x 1 ohba wheel 669 11/ 5 13:23 setup.sh -rw-r--r-- 1 ohba wheel 94 12/22 2000 spec
アクセス権を変えるには、chmod コマンドを用いる。例えば、
詳しくは、man chmod (または、jman chmod)を見ること。chmod a+x file名 (すべてに実行権を与える) chmod a-x file名 (すべてに実行権を与えない) chmod 755 file名 (すべてに読み込みと実行権を与える、書き込みは所有者だけ) chmod 644 file名 (すべてに読み込みを与える、書き込みは所有者だけ、実行権はない)
あるコマンドを実行したとき、Unix のシェルはそのコマンドが何処にあるかを、環境変数 $PATH に従って検索する。例えば
となっていれば、/home/ohba/bin /usr/local/jdk/bin の順番に与えられたコマンドを 探す。したがって、自分が作った実行ファイルは、ホームディレクトリの bin という ディレクトリーに置けばよい。そうすれば、どこのディレクトリからでもコマンド名だけで 直接実行出来る。% echo $PATH /home/ohba/bin:/usr/local/jdk/bin:...省略...:/bin:/sbin:/usr/local/interviews/bin
ただし、$PATH にどういうプログラムがあるかを、シェルはシェルが起動した 時に覚える。したがって、あるプログラムを ~/bin/ に置いた直後は、その シェルは、~/bin/のファイルの変更を知らない。変更を反映させるためには、 一度、
と打つ。% rehash
とりあえず作ったコマンドを実行するのに、いちいち bin に置かないといけないのか、というと そんなことはない。コマンドを フルパスで打てば、$PATH に関係なく実行される。例えば、
で、どこのディレクトリからでもこのプログラムが実行される。また、カレントディレクトリに ある実行形式のファイルは、% /home/ohba/gnuplot/setup.sh
で実行される。% ./ファイル名
例えば、/usr/local/bin 以下にどのようなファイルがあり、いつ、それらが作られたかを
調べるためには、
と入力するが、これでは出力が画面を流れてしまい、最後の方しか見ることが できない。そこで、% ls -l /usr/local/bin
とすると、ls -l /usr/local/bin の出力を、ページャー(less)に入れてみ ると、最初からじっくりと見ることが出来る。ひとつのコマンドの標準出力を、 他の標準入力に結び付けることをパイプ(またはパイプライン)と言い、 "|" を使う。また、上の結果をファイルとして保存したい場合には、% ls -l /usr/local/bin | less
というようにする。このように、標準出力(入力)をファイルに結び付けるこ とを、リダイレクト(またはリダイレクション)と言い、 ">",">>", "<" などの記号を使 う。詳しい解説は、 コンピューター基礎教育のテキストを参照。このように Unix では、少しの仕事をするいくつかのコマンドを組合せて使うことで、自 分が行いたい処理を簡単にかつ柔軟に行わせることが出来る。いくつかの例を 示そう。% ls -l /usr/local/bin > file.txt
テキストで、gnuplot でデータをプロットする際に、% ls -l /usr/local/bin | grep tex | less (/usr/local/bin の下の tex を含むファイルを less で表示) % ps aux | sort > ps.txt (現在、走っているすべてのプロセスを、ユーザー名でソートして、ps.txt に保存) % ps aux | grep -v USER | wc -l (現在、走っているすべてのプロセスの数を表示) % grep http * | grep -v stex | less (カレントディレクトリのすべてのファイルから、http を含み stex を含まない行を less で表示)
となっている部分は、予め、シェルのコマンドラインで、gnuplot>plot "<raw rf1500.txt"
としてから、% raw rf1500.txt > rf1500.dat (または、raw < rf1500.txt > rf1500.dat でも同じ)
としても同じである。gnuplot>plot "rf1500.dat"
raw というプログラムは、RF1500 から取り込んだ実験条件などのヘッダー付 きのファイルから、ヘッダー部分を除いて、gnuplot でプロットできる形式に 変換し、標準出力に出す。プログラムの中味は次のようになっている。行番号と 赤い字は、説明のためで、実際のプログラムにはない。また、プログラム中で、 リンクが張ってあるコマンドをクリックするとそのマニュアルページを開く。
1 #!/usr/local/bin/perl # perl のプログラムであるとの宣言 2 # 目的 # 以下はコメント行(実行には無関係) 3 # 第1引数のファイル(指定しない場合は標準入力)から 4 # 各行の最初の列がゼロ以外の数字である行を標準出力に出す。 5 # つまり、数値データから余分なヘッダーを除く。 6 # 空行も無関係 7 # read data 8 $n=0; # スカラー変数は、$から始まる 9 while(<>){ # <>はファイルハンドル。引数のファイルから一行ずつ読み込み、空になるまで続ける 10 chop; # 行末の改行文字を削除 11 ($x[$n],$y[$n])=split; # 空文字(スペース、タブ)で分けて、最初のふたつを代入、3つ以上ある場合は無視 12 if($x[$n]!=0){$n++;} # 最初の変数がゼロ以外の数字の場合のみ、配列要素を増やす。 # つまり、数字以外の場合は、次の読み込みで上書きされて消える。 13 } 14 15 16 # output 17 for($i=0;$i<$n;$i++){ 18 print "$x[$i]\t$y[$i]\n"; # ふたつの数値配列をタブ(\t)で区切って出力する。 # 出力先のファイルハンドルを省略すると、標準出力に出す。\nは改行。 19 }9〜11行目あたりが、他のプログラム経験があって、perl を知らない人には、 意味不明になるところである。
open(IN,"ファイル名"); while(<IN>){ } close(IN);と、ファイルをオープンするときに付けた名前に対応させる。ハンドル名が 省略された<>(ヌルファイルハンドル)に対し、perl はコマンドが呼ばれたときの引 数があるかどうかをチェックし、ある場合にはそれらを順番に開いて読み込 む。引数がない場合には、標準入力から読み込もうとする。したがって、raw コマンドの 次のふたつの使い方は、全く同じことを行う。
raw ファイル名 cat ファイル名 | raw9〜11行目で 読み込まれた行は、どこに格納されるのか?
以上をふまえると、
while(<>){ chop; ($x[$n],$y[$n])=split; }の部分は、
unshift(@ARGV, '-') if $#ARGV < $[; while ($ARGV = shift) { open(ARGV, $ARGV); while ($line=<ARGV>) { $choped_line=chop($line); ($x[$n],$y[$n])=split(/[ \t\n]+/,$choped_line,3) ; } }と書いても同じである。どちらでも perl は同じ結果を出す。違いといえば、 最初の方が、プログラムを書く手間が省けることだけだろう。
このように perl は、プログラマーの意図を出来る限り読み取り、意味が通じ る限りデフォルトで補って、実行可能なコードを生成しようとする。したがっ て、最小限のプログラムで、多くの仕事をさせることが出来る。もちろん、こ のようなコーディングスタイルは、大規模なプログラムを作る場合には、潜在 的にバグが潜り込む可能性が高くなる。その場合には、もっと厳密なコーディ ングをすればよいのであって、厳密なコーディングには perl はそのまま答え てくれる。この辺りのことを、「perl は、難しい仕事を不可能にす ることなしに、簡単な仕事を簡単に出来るように設計されている」 と Larry Wall(perl の作者)は書いている。
ここでは、実験2で用いる anisotropy というプログラムを 解説し、実験の際にゼロ点がずれたまま測定してしまった場合に、データ処理で それに最低限の補正を加えるようにプログラムを変更する方法を述べる。 (これは例として掲げているだけで、実験ではゼロ点を正しくセットしてから 行うのが基本である。)
解説はこちら