2部 Perl言語仕様

制御構文

条件文

条件文はいくつかの選択肢をコード内で実現したい際に使用します。「もし~ならば、・・・を実行する」、「もし~ならば、・・・を実行しない」といったように条件によって処理を実行したり、いくつかの選択肢の中からひとつの処理を実行したりといったことを実現することができます。

if文

「もし~ならば、・・・を実行する」という条件つきの命令を実現するために、if 文が用意されています。if文は、カッコの中の条件式を評価し、TRUE のときだけ if ブロックの命令文を実行します。

構文
if ( 条件式 ) {
	処理....
}

変数 $var の値が A の時だけ出力するには次のようになります。

if ( $var eq 'A' ) {
	print "Aです\n";
}

条件式は複数あってもかまいません。複数の条件を並べたいときは、論理演算子の and もしくは or を使います。

# or: $var が A、 もしくはB のとき、命令文を実行
if ( $var eq 'A' or $var eq 'B' ){
	....
}
# and: $var1 が A 、$var2が B のとき、命令文を実行
if ( $var1 eq 'A' and $var2 eq 'B' ){
	....
}

else 文で例外処理をする

if 文では、条件式が TRUE のときに命令文を実行しましたが、条件式が FALSEだった場合は、else 文で例外処理を行うことができます。

構文
if ( 条件式 ) {
	処理....
} else {
	処理....
}

次の例文では、変数 $var の値によって処理を振り分けています。

if ( $var eq 'A' ) {
	print "Aです\n";
} else {
	print "Aではない\n";
}

以上のように、if ~ else によって、条件文が TRUE でも FALSEでも何らかの処理を行うことができます。

if 文で複数の条件分岐を処理する

if 文は複数の条件分岐にも使えます。if の条件式が FALSEであった場合、さらにほかの条件式をためしたいときは、elsif 文を使います。どの条件式も FALSEだった場合は、else 文を使って例外処理を行うことができます。else はどの条件式も FALSEだったときのみ実行されます。

構文
if ( 条件式 ) {
	処理....
} elsif ( 条件式 ) {
	処理....
} else {
	処理....
}

次の使用例は、変数の値によってメッセージを変えています。

if ( $var eq 'A' ) {
	print "Aです";
} elsif ( $var eq 'B' ) {
	print "Bです";
} else {
	print "AでもBでもない";
}

unless文

unless文は、if 文の逆の判定をします。条件式が FALSE のときにブロックの式を実行します。

構文
unless ( 条件式 ) {
	....
}

変数 $var の値が A の以外の時だけ出力するには次のようになります。

unless ( $var eq 'A' ) {
	print "Aではありません\n";
}

はじめのうちは、unless 文を使わないことをお勧めします。なぜなら、if文で同様のことを行えるからです。

次の2つの条件分岐はまったく同じ動作をします。

unless ( $var eq 'A' ) {
	print "Aではありません\n";
}
if ( $var ne 'A' ) {
	print "Aではありません\n";
}

短いプログラムであれば unless文の使用はそれほど問題になりませんが、長いプログラムになると上記のような使い方が入り乱れる可能性があり、あまりよいコーディングスタイルとはいえません。unless文を使うときはよく考えてからにしましょう。

繰り返し構文

条件が成立する間処理を繰り返したいときには、繰り返し構文を利用します。繰り返し構文には、while、until 、for 、foreach 、do 文があります。

while文

while文は、条件式が真を返す限り、ブロック内を実行します。

構文
while ( 条件式 ) { 
	...
}

下記の例では、 $countが10以下である間、ブロック内の処理を繰り返し実行します。

$count = 0;
# $count が10以下であるかぎり繰り返す
while ( $count < 10 ) {
	....
	# $countをインクリメント
	$count++;
}

ループの間、条件が決してFALSEにならない場合、命令が永遠に実行されることになるので、注意が必要です。上記スクリプトで、$countをカウントしていかないと、$countは初期値の0のままなので永遠に処理が繰り返され続けます。

while文が最もよく使われるのが、ファイルの読み込み時です。下記の例では、while文の条件式の中で行、入力演算子 <>を使ってファイルハンドルに関連付けられたファイルを行単位で読み込んでいます。

open( DAT, "test.dat" );
# "test.dat"を1行ずつ読み、出力する
while ( $line = <DAT> ) {
	print $line, "\n";
}
close( DAT );

until文

until文はwhile文の反対で、条件式が偽の間、ブロックを実行します。

構文
until (条件式) {
	...
}

使い方は while 文と同様です。

$i = 1;
# 1から10まで出力する
until ( $i > 10 ) {
  print "$i\n";
  $i++;<
}

ifとunless文の関係と同様に、until文で処理できることはwhile文でも処理できるので、特別な理由がなければwhile文を使うほうがよいでしょう。

for文

for文は、他のループ文と同じように式を評価してブロックを実行します。while文と大きく違う点は、何回ループするかを明示的に指定することができることです。

構文

for ( 式1; 式2; 式3 ) { .... }

最初の式1は、ループのブロックが実行される前に、ループインデックスと呼ばれる、ループする回数を指定するための変数を初期化します。式2は条件を評価し、真であればループのブロックを実行し、偽であればループを終了させます。式3はループの繰り返しの後に実行され、ループインデックスを増減させます。

for文の処理手順
  1. 式1の初期値の設定を行います。これは一度のみ行われます。
  2. 式2の条件判断を行い、TRUE の場合はループのブロックを実行します。FALSE
    の場合はループ外へ抜けます。
  3. ブロック内の命令を実行します。
  4. 式3にあるループインデックスの増減処理を行います。
  5. 2 に戻ります。
for ( $i = 1; $i <= 10; $i++ ) {
	print $i, "\n";
}

特殊な条件式

for文の条件式はセミコロン( ; )で式1から式3を区切りますが、さらに式をカンマ( , )で区切り、2つの変数に対して繰り返しを行うこともできます。

for ( $u = 0, $d = 10; $u < $d; $u++, $d-- ){
	print "$u $d\n";
}

foreach文

foreachは、リストの1番目から順番に変数に代入していき、ブロックを実行します。リストが終了した時点で繰り返しが終了されます。

構文

foreach 変数 ( リスト ) { ブロック }

配列の要素の和を求める
@int = (1,2,3);
$total = 0;
foreach $j( @int ) {
  $total += $j;
}
print"$total";
> 6

split などが返すリストなどもそのまま foreach の式として使えます。

foreach my $value ( split(/ /, $val) ) {
    print "値: $value\n";
}

do文

do-while 構文は条件が真の間、do-until構文は偽の間、ブロックを実行します。判定はブロックを実行した後になります。

構文

do ブロック while 条件
do ブロック until 条件

次の例文では、while の条件が TRUE の間、doブロック内の処理を続けます。

$i = 0;
do {
	$i++;
	print "$i\n";
} while ( $i < 10 );

ループ制御コマンド

Perlには、ループ文を制御するのに便利なループラベルが多数用意されています。すべてのループ文には、ラベルをつけることができます。ラベルは、識別子の後ろにコロンをつけたもので、予約語との衝突を避けるために、大文字を使う習慣になっています。

ループ制御コマンド next、last、redo は、ラベルによって対象となるループを指定します。

next

next は、ループブロック内の nextに続くすべての命令文をスキップして、次の繰り返しに移行します。

while( <> ){
	next if /^\d+/; # 行頭に数字がある場合はスキップ
	....
}

nextにラベルを指定すると、ループの外にあるラベルに移行することができます。

OUTER: while( <>){
	....
	INNER: foreach( @list ){
		MYLABEL: {	# このように、単にブロックだけというのも可能
next OUTER if /^\d/; } } }

continue

continue がある場合は、条件部を再び評価する直前にそれが実行されます。ですから、nextなどで処理を飛ばした場合でも、continue ブロックは必ず実行されます。

for ( $1 = 1; $i < 10; $i++ ){
	...
}
# 上記 for 文とまったく同じ動作をする
$i = 1;
while ( $i < 10 ){
	...
} continue {
	$i++;
}

last

last は現在のループをただちに終了します。ループに continue がある場合でも、実行しません。

次の例は、行頭に数字があると、ループから脱出します。

while( <> ){
	last if /^\d/;
}

next ラベルと同じように、{ } で囲まれたブロックにラベルをつけ、 lastなどで対象とするブロックを指定することができます。

MYLABEL: foreach $val ( @array ) {
	print "$val\n";
	for( $i = 0; $i < 10; $i++ ) {
		# 一番外側のループ(foreach)を抜ける
		last MYLABEL if( $i == $val );
	}
}

redo

redo 文は、next文とよく似ていますが、ループの条件チェックを行わないで、ループの先頭に制御を移します。continueブロックも無効です。

while ( $line = <> ) {
	....    # 何らかの処理
	redo if ....;    # 何らかの条件にマッチした場合、ループの先頭に戻す
}

goto

goto は C言語に親しんだ人用に用意されていますが、ほとんど利用する必要性はありません。last やnext 等のラベルや die などで十分に代用することができます。

関連記事