Perl5perlsyn - Perl の構文
[DESCRIPTION][単純実行文][複合実行文]
複合実行文
Perl では、スコープが定義される実行文の列をブロックと呼んで います。
ときにはブロックは、そのブロックを含むファイルの単 位で区切られ (この場合 require で読み込まれるか、プログラム 全体ということになります)、また文字列として区切られる場合も あります (eval される場合です)。
しかし、一般にはブロックは中括弧 (`{}') で区切られるのが普通 です。
この構文上の構造を BLOCK と呼ぶことにします。
以下の複合実行文を、流れの制御のために使うことができます:
         if (EXPR) BLOCK
         if (EXPR) BLOCK else BLOCK
         if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
         LABEL while (EXPR) BLOCK
         LABEL while (EXPR) BLOCK continue BLOCK
         LABEL for (EXPR; EXPR; EXPR) BLOCK
         LABEL foreach VAR (ARRAY) BLOCK
         LABEL BLOCK continue BLOCK
C や Pascal と違って、文ではなく、BLOCK を使って定義されてい ることに注意してください。
これは中括弧が必須ということで、 中ぶらりんの実行文が許されないということです。
中括弧を使わ ないで条件を書きたい場合には、方法がいくつかあります:
         if (!open(FOO)) { die "Can't open $FOO: $!"; }
         die "Can't open $FOO: $!" unless open(FOO);
         open(FOO) or die "Can't open $FOO: $!";     # FOO or bust!
         open(FOO) ? 'hi mom' : die "Can't open $FOO: $!";
                             # a bit exotic, that last one
はすべて同じことをします。
if 文は見た通りです。
BLOCK は必ず中括弧で括られますから、 if と else の対応が曖昧になることはありません。
if の代わり に unless を使えば、テストの意味が逆になります。
while 文は、式が真である間 (評価結果が、空文字列、0、"0" の いずれかでない間) ブロックを実行します。
LABEL はあっても無 くてもよく、もし存在する時には、識別子にコロンを続けたもので す。
LABEL は、next、last、redo というループ制御文が、ルー プを識別できるようにするものです (以下を参照)。
continue BLOCK があれば、C の for ループの 3 番目の部分のように、次に 条件が評価される直前に実行されます。
ですから、(C の continue 文と同様に) たとえ next 文でループを進めるときにも、 ループ変数のインクリメントが行なうことができます。
while を until で置き換えると、テストの意味が逆になりますが、 繰り返しの前に、条件が評価されることは変わりません。
if 文または while 文において、"(EXPR)" を BLOCK で置き換える ことができ、ブロックの最後に実行した文が真であれば、条件も真 となります。
(この機能は Perl 5 でも機能しますが、使わない ようにしてください。
"if BLOCK" の代わりに "if (do BLOCK)" とすればよいでしょう。)
C スタイルの for ループは、完全に対応する while ループと同じ ように動作します:
         for ($i = 1; $i < 10; $i++) {
             ...
         }

     は、

         $i = 1;
         while ($i < 10) {
             ...
         } continue {
             $i++;
         }
と同じことです。
foreach ループは通常のリスト値で繰り返しを行ない、変数 VAR にそのリストの値を順番に設定します。
その変数は、(前もって my で宣言したのでなければ) 暗黙のうちにループ内にローカルと なり、ループを抜けると以前の値に戻ります。
キーワードの foreach は、実際にはキーワード for の同義語であり、読みやす さのために foreach を、簡潔さのために for を使い分けることが 可能です。
VAR を省略すると、$_ に個々の値が順に設定されま す。
もし、ARRAY が (リスト値を返す式ではなく) 本物の配列の 時には、ループの中で VAR を修正することによって、その時に対 応している配列の要素自身を修正することができます。
例:
         for (@ary) { s/foo/bar/; }

         foreach $elem (@elements) {
             $elem *= 2;
         }

         for ((10,9,8,7,6,5,4,3,2,1,'BOOM')) {
             print $_, "\n"; sleep(1);
         }

         for (1..15) { print "Merry Christmas\n"; }

         foreach $item (split(/:[\\\n:]*/, $ENV{'TERMCAP'})) {
             print "Item: $item\n";
         }
BLOCK 自身は (ラベルが付いていても、いなくても) 意味的には、 1 度だけ実行されるループと同じです。
つまり、ブロックを抜け たり、再度実行したりするのに、ループ制御文が使えるということ です。
continue BLOCK はあっても無くてもかまいません。
こ の構成は、case 構文を組み立てるのに便利です。
         SWITCH: {
             if (/^abc/) { $abc = 1; last SWITCH; }
             if (/^def/) { $def = 1; last SWITCH; }
             if (/^xyz/) { $xyz = 1; last SWITCH; }
             $nothing = 1;
         }
Perl には、公に switch 文は存在しません。
同値なものが既に いくつもあるからです。
上にあげたものの他に、
         SWITCH: {
             $abc = 1, last SWITCH  if /^abc/;
             $def = 1, last SWITCH  if /^def/;
             $xyz = 1, last SWITCH  if /^xyz/;
             $nothing = 1;
         }
とも書けます。
(これは、ループ制御「演算子」を式の中で使え ることに気が付けば、見た目ほど奇妙なものではありません。
普 通の C のコンマ演算子です。)
また、
         SWITCH: {
             /^abc/ && do { $abc = 1; last SWITCH; };
             /^def/ && do { $def = 1; last SWITCH; };
             /^xyz/ && do { $xyz = 1; last SWITCH; };
             $nothing = 1;
         }
とも書けますし、もう少し「正当な」switch 文のように整形する と:
         SWITCH: {
             /^abc/      && do {
                                 $abc = 1;
                                 last SWITCH;
                            };

             /^def/      && do {
                                 $def = 1;
                                 last SWITCH;
                            };

             /^xyz/      && do {
                                 $xyz = 1;
                                 last SWITCH;
                             };
             $nothing = 1;
         }
となりますし、
         SWITCH: {
             /^abc/ and $abc = 1, last SWITCH;
             /^def/ and $def = 1, last SWITCH;
             /^xyz/ and $xyz = 1, last SWITCH;
             $nothing = 1;
         }
や、醜くも
         if (/^abc/)
             { $abc = 1 }
         elsif (/^def/)
             { $def = 1 }
         elsif (/^xyz/)
             { $xyz = 1 }
         else
             { $nothing = 1 }
としてもよいでしょう。

出典:Perl manpages Last change: Release 5.0 Patchlevel 00 5