if は「もし」を意味します。(...) の中には条件式を書きます。下記の例では、もし $num の値が 5 であれば「5です。」を表示します。== は「数値が等しければ」を意味します。(→ 算術比較演算子)
$num = 5; if ($num == 5) { print "5です。\n"; }
条件節を後ろに書くという英語の文法にマッチするように、次のように記述することもできます。
$num = 5; print "5です。\n" if ($num == 5);
if (...) { ... } の形式では、実行文が1行であっても、{ と } を省略することはできません。
unless は「もし~でなければ」を意味します。下記の例では、もし $num の値が 5 でなければ「5ではありません。」を表示します。
$num = 3; unless ($num == 5) { print "5ではありません。\n"; }
if 文と同様、次のように記述することもできます。
$num = 3; print "5ではありません。\n" unless ($num == 5);
else は「さもなくば」を意味します。もし、$num の値が 5 であれば「5です。」を、さもなくば、「5ではありません。」を表示します。
$num = 3; if ($num == 5) { print "5です。\n"; } else { print "5ではありません。\n"; }
else を unless に使用することもできます。訳がわからなくなりますが・・・。
unless ($num == 5) { print "5ではありません。\n"; } else { print "5でないことはないです。\n"; }
elsif は else if の略で、「さもなくば、もし」を意味します。$num の値が 5 であれば「5です。」を、6 であれば「6です。」を、7 であれば「7です。」を、さもなくば「5でも6でも7でもありません。」と表示します。
$num = 6; if ($num == 5) { print "5です。\n"; } elsif ($num == 6) { print "6です。\n"; } elsif ($num == 7) { print "7です。\n"; } else { print "5でも6でも7でもありません。\n"; }
elsif はいくつでも記述することができます。C言語のように else if と書いてしまったり、elseif とスペルミスしないようにしましょう。
for は繰り返しを処理します。まず $i に 0 を代入し、$i の値をひとつ加算しながら、$i の値が 10 未満である間、つまり、$i が 0 から 9 までの間、print 文を繰り返して実行します。
for ($i = 0; $i < 10; $i++) { print "i = $i\n"; }
これも、print 文を 10回繰り返します。$i は 1 から 10 までの値をとります。
for $i (1..10) { print "i = $i\n"; }
$i を省略して for (1..10) とすることもできます。この場合、$i の代わりに省略時変数 $_ が用いられます。
for (1..10) { print "i = $_\n"; }
for (;;) は無限にループを繰り返します。下記の例では、キーボードから q と入力するまで、永遠にループを繰り返します。
for (;;) { print "> "; $str =<>; chop($str); if ($str eq "q") { last; } print "$str\n"; }
foreach は配列のそれぞれの要素に対して、ひとつずつ処理を行います。$name に "Tanaka", "Suzuki", "Yamada" を順に代入しながら処理を繰り返します。
@namelist = ( "Tanaka", "Suzuki", "Yamada" ); foreach $name (@namelist) { print "NAME = $name\n"; }
実行結果は次のようになります。
NAME = Tanaka NAME = Suzuki NAME = Yamada
$name を省略した場合は、$name の代わりに省略時変数 $_ が用いられます。
@namelist = ( "Tanaka", "Suzuki", "Yamada" ); foreach (@namelist) { print "NAME = $_\n"; }
while は (...) が真である間処理を繰り返します。下記の例では $num の値をひとつずつ増やしながら、$num が 10 より小さい間、処理を繰り返します。
$num = 0; while ($num < 10) { print "$num\n"; $num++; }
次のように記述することもできます。この場合、(...) が偽であっても、必ず1度は処理が実行されます。
$num = 0; do { print "$num\n"; $num++; } while ($num < 10);
until は (...) が真になるまでの間処理を繰り返します。下記の例では、$num が 10 になるまでの間、処理を繰り返します。
$num = 0; until ($num == 10) { print "$num\n"; $num++; }
while 文と同様、次のように記述することもできます。この場合も、必ず1度は処理が実行されます。
$num = 0; do { print "$num\n"; $num++; } until ($num == 10);
last は、ループ(for、foreach、while、until)を途中で中断して抜けます。JavaScript や C言語の break文に相当します。下記の例では、$i の値が 5 の時に、ループをを抜けます。
for ($i = 0; $i < 10; $i++) { if ($i == 5) { last; } print "i = $i\n"; }
ループが多重にある場合は、もっとも内側のループを抜けます。
for ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 10; $j++) { if ($j == 5) { last; } # $j のループを抜ける print "i = $i, j = $j\n"; } }
next はループ(for、foreach、while、until)の残りの処理をとばして、次のループを実行します。JavaScript や C言語の continue に相当します。下記の例では、$i が 5 の時に print 文を実行しないで次のループに移ります。
for ($i = 0; $i < 10; $i++) { if ($i == 5) { next; } print "i = $i\n"; }
ループが多重にある場合は、最も内側のループに対して next が実行されます。
for ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 10; $j++) { if ($j == 5) { next; } # $j のループを next する print "i = $i, j = $j\n"; } }
redo は最も内側のループの、今現在行っているループをもう一度繰り返します。redo を行ってもカウントアップしない点が next と異なります。あまり利用されていませんが、カウントを数えながら処理を再トライするさせる場合などには便利です。
print "1~5の数字を3つ入力してください。\n"; for ($n = 1; $n <= 3; $n++) { print "$n個目> "; $num[$n] = <STDIN>; chomp($num[$n]); if (($num[$n] < 1) || (5 < $num[$n])) { print "ちょっと変です。\n"; redo; } } print "$num[1], $num[2], $num[3] ですね。\n";
continue { ... } には、while の次のループを実行する直前の処理を記述します。下記の例は for ($i = 0; $i < 5; $i++) { ... } と同じ動作となります。
$i = 0; while ($i < 5) { print "$i\n"; } continue { $i++; }
C言語にも continue 文がありますが、意味は異なります。C言語の continue は Perl の next に相当します。
goto 文は、ラベル名: の場所にジャンプします。下記の例では、phase 1 の処理を行った後、phase3 の箇所にジャンプします。
print "phase 1.\n"; goto phase3; print "phase 2.\n"; phase3: print "phase 3.\n";
プログラミングの本にはよく「goto 文を用いるとプログラムの流れが繁雑になるので、goto 文を用いるべきではない。」と書かれています。しかし、下記のようにエラー処理に限った使い方であれば非常に便利なので、このケースに限っては、私は goto 文を愛用しています。
$err = CopyFile("xx1.dat", "xx2.dat")) || print "$err\n"; # ファイルをコピーする sub CopyFile { local($from, $to) = @_; local($err, *IN, *OUT, $line); if (!open(IN, $from)) { $err = "ファイル $from を開けません。\n"; goto done; } if (!open(OUT, "> $to")) { $err = "ファイル $to を開けません。\n"; goto done; } while ($line = <IN>) { if (!print OUT $line) { $err = "書き込みが失敗しました。\n"; goto done; } } done: # 後処理をすべて done 以降に記述してしまう close(IN); close(OUT); return $err; }
exit はプログラムを途中で終了します。引数はプログラムの実行結果を返します。通常、プログラムが正常に終わるときには 0 を、プログラムが異常で終わるときには 0 以外の値を指定します。CGI の場合は、引数は無視されます。
if (!open(IN, $file)) { print "ファイルを開けませんでした。\n"; exit(1); }
UNIX では、プログラムの実行結果を次のようにして確認することができます。(csh 系シェルの場合)
% echo $status 0 %
制御構文ではありませんが、die() もプログラムを終了します。加えて、終了時のメッセージを出力します。出力は標準エラー出力(STDERR)に行われますので、CGI ではあまり die を用いません。
open(IN, "data.txt") || die "data.txtを開けません。\n";
メッセージの末尾が改行でなければ、スクリプトファイル名と行番号が付加されます。
open(IN, "data.txt") || die "Can't open data.txt";
実行結果は次のようになります。
Can't open data.txt at flow5.pl line 1.