| Top Page | プログラミング | Perl 目次 | prev | next | 索引 |

9. コマンドラインで与えたパラメータを使う

コマンドライン引数

これまで,Perl のプログラムを起動するときに後ろにファイル名を書いて, これを読み込んで処理するという例がいくつも出てきました.

プログラム名のうしろに書けるのはファイル名だけではありません. 好きなだけ文字列を書き連ねることができます. それらの文字列をコマンドライン引数(ひきすう)と呼びます. コマンドライン引数は,Perlの処理系が用意している特別な配列 @ARGV に しまわれています.

コマンドラインに書いたファイルから1行づつ読み込むのに,$line = <>; などと書いていました(>4. ファイルからの入力とsplit). この文は,@ARGV にしまわれている文字列をファイル名として解釈して (複数あってもよい),それらのファイルからデータを読み込む, という機能を持っていたのです. もし @ARGV がからっぽ,すなわち要素数がゼロだったら,ファイルからは読み込めないので キーボードからの入力待ちになります.

コマンドラインに書いたファイル名の利用法は,つぎのページでも解説します.


コマンドラインでパラメータを指定する

コマンドライン引数として書けるのは,ファイル名だけではありません. @ARGVにしまわれた文字列はどのように解釈しようとプログラムの勝手です. 配列の扱い方はすでに勉強したので, @ARGVも自由に扱えますね.

コマンドラインに,計算処理に必要な数値を書いてみましょう. 関数 rand の利用法を紹介したページ では,四角形内のランダムな点の分布パターンを生成するプログラムを とりあげました.このプログラムでは,点の数と分布範囲をプログラム中に 書き込んでいました.

$points = 100;  # 点の数
$max_x = 50;    # x軸方向の長さ
$max_y = 40;    # y軸方向の長さ

今度は,点の数,x軸方向の長さ,y軸方向の長さをコマンドライン引数で 指定できるようにしてみます.

#  rand_points.pl: 四角形内のランダムな点の分布パターンを生成する

$points = shift @ARGV;  # 点の数
$max_x = shift @ARGV;   # x軸方向の長さ
$max_y = shift @ARGV;   # y軸方向の長さ

if ( !(defined($max_y)) ) {  #  引数が足りないと,$max_y は未定義になるはず.
    #  正しい使用法を表示して,実行を終了する.
    die "USAGE: perl rand_points.pl num_points max_x  max_y";
}

for ($i = 0; $i < $points; ++$i) {    #  点の数だけ繰り返す.

    $x = rand();         #  rand ()は0以上1未満の乱数を返す.
    $y = rand(); 

    $x = $x * $max_x;     #  [0, 1) の範囲の値を [0, $max_x)の範囲の値へ.
    $y = $y * $max_y;     #  [0, 1) の範囲の値を [0, $max_y)の範囲の値へ.

    printf "%.2f\t%.2f\n", $x, $y;    # $x, $y それぞれ小数点以下2ケタまで表示.
}

DOS窓(ないしは仮想端末)で実行するには,たとえば

 perl rand_points.pl 100 40 40

のように入力します.

$points = shift @ARGV; のように,@ARGV に対して shift を実行するたびに, コマンドライン引数が前のほうから順に取り出されます.その分だけ,@ARGVの 要素は減っていきます.

上のプログラムでは3個の引数を期待しています.引数の数が3個未満だと, $max_y = shift @ARGV; を実行する時点では @ARGV はからっぽになってます. 空の配列からデータを取り出そうとすると,未定義値が返ってきます. これを利用して,引数の数が足りてるかをチェックしているのが if ( !(defined($max_y)) ) のところです.

この例のように,正しく引数が与えられなかったら使い方を表示するように しておくと,他の人(3日後の自分を含む)が使いやすくなります.

今度は,配列の活用のページの最初に出てきた, 気温データを読み込んで積算温度を計算・出力するプログラムをいじってみます. 温度の閾値(生物学的0度)を,プログラム中で用意するのではなく, コマンドライン引数として指定します. こんどは気温データを一度配列にしまう必要はないので,一行読むごとに 積算温度とともに表示していきます.

# deg_day.pl  積算温度を計算する.

if (@ARGV < 2) {  # 引数の数をチェック(配列をスカラーコンテキストで評価)
    die "USAGE:  perl deg_day.pl biol_zero  temperature_data_file\n";
}

$zero = shift @ARGV; # 最初のコマンドライン引数が閾値

$degree_day = 0.0;   #  温度の積算を始めるまえに 0 に初期化(必須ではない).

while ($tmp = <>) {         # 気温データファイルを順次読んで行く.
    chomp $tmp;             # 末尾の改行を削除
    if ($tmp > $zero) {     #  閾値より高温だったら…
        $degree_day += ($tmp - $zero);    #  高い分だけ積算温度に加算
    }
    print $tmp, "\t", $degree_day, "\n";  # 気温と積算温度を表示
}

目新しいのは,if (@ARGV < 2) のところです. 配列と数値との比較をしていますが,この場合,配列の要素数が数値と比較されます. 数値と大小比較する,という「場」に置かれた配列は,要素の数をその値とします. だから,if (@ARGV < 2) では引数がちゃんと2つあるかどうかをチェックしてることになります.

このような配列のふるまいは, スカラー変数(「ふつうの」変数)に配列やリストを代入しようとすると 要素数が代入されたのとよく似ています( 配列の説明 を参照 ).「スカラー変数 = 配列」という文脈に置かれた配列は,要素数をその値と したのでした.

ここまでの説明で「場」とか「文脈」とか表現されたものを,Perl では コンテキストと呼びます.配列やリストが期待される「場」を リストコンテキスト, スカラー変数やリテラルが期待される「場」をスカラーコンテキストと 呼びます.

なにやら抽象的ですが,これからもおいおい説明します.とりあえずは 配列を数値と大小比較したり,配列をスカラー変数に代入しようとすると 要素数が比較されたり代入されたりするということだけ覚えておいてください.



| Top Page | プログラミング | Perl 目次 | prev | next |