この項目では、Perlの制御構造について説明します。
以下の構文説明では、EXPRは式、BLOCKはコードブロック、VARは変数、LISTはリスト、LABELはラベルを示します。
角括弧 [ ] で囲まれたものは省略可能です。
波括弧 { } で囲まれたものは0回以上の繰返しが可能です。
Perlの分岐構文には、if,unlessがあります。
かつて given/when/default 構文の実験的実装がありましたが、Perl6（現在のRaku）のテストベッドに使っただけらしく、幾つかのバグが発見され、Perl-5.24 ではレキシカルな $_ の仕様がキャンセルされるなど、言語コアにも取り込まれていないので、ここでは扱いません。
if文によって、ある条件をみたしているかを判定し、判定の内容により動作を切り替えることができます。 
[https://paiza.io/projects/6piOAvS2y7b7IdKQxzU85w?language=perl 例]:
use v5.12;
use warnings;
my $x = 5;
if ($x > 1) { say '$xの値は1より大きい'; }
実行結果:
$xの値は1より大きい
上記の例の場合、変数 $x が 1 より大きいかどうかの区別を判定しています。
[https://paiza.io/projects/6UG7P5DLG9viFe8eg8Qp5w?language=perl 複数行の例]:
use v5.12;
use warnings;
my $x = 5;
if ($x > 1) {
  say '$xの値は1より大きい';
}
のように改行して書いても、構いません。
elseは「さもなければ」という意味で、直前のif文の条件が満たされていない場合の処理を担当します。
elseのないifはありますが、ifのないelseはありえません（else節はif構文の構成要素の１つです）。
[https://paiza.io/projects/56olWLNhsHzEtfh2kKdrFQ?language=perl 例]:
use v5.12;
use warnings;
my $x = 5;
if ($x > 9) {
    say '$xの値は9より大きい';
} else {
    say '$xの値は9以下';
}
実行結果:
$xの値は9以下
elsif ( 式 ) BLOCK  は、else { if ( 式 ) BLOCK }の構文糖です。
なお、elifでもelseifではなくelsif です。
[https://paiza.io/projects/MxhZKvYenI_bRHeU8rpk8A?language=perl 例]:
use v5.12;
use warnings;
my $x = 2;
if ($x > 3) {
  say '$xは3より大きい';
} elsif ($x > 1) {
  say '$xは4より大きい';
} else {
  say '$xは1以下';
}
実行結果:
$xの値は4より大きい
先行するifの条件が成立せず、elsifの条件式が成立しているのでelsifの BLOCK が実行されます(そしてelseのBLOCKは実行されません）。
[https://paiza.io/projects/I6x3PBpM65PbxBhfXUj3Lw?language=perl 例]:
use v5.12;
use warnings;
my $x = 5;
if ($x > 3) {
  say '$xの値は3より大きい';
} elsif ($x > 4) {
  say '$xの値は4より大きい';
} else {
  say '$xの値は1以下';
}
実行結果:
$xの値は3より大きい
先行するifの条件がしているのifのBLOCKが実行され、elsifの条件式の成否にかかわらずelsifの BLOCK は実行されません(そしてelseのBLOCKも実行されません）。
構文:
if ( EXPR ) BLOCK { elseif (EXPR) BLOCK }* [ else BLOCK ]
英語でunlessは「もし…でなければ」という意味です。
Perlのunlessは、EXPRが偽の場合、BLOCKを実行します。
[https://paiza.io/projects/8dDFQy40Q7sNRj8XN5cX_w?language=perl 例]:
use v5.12;
use warnings;
my $x = 5;
unless ($x <= 1) { say '$xの値は1以下でない'; }
実行結果:
$xの値は1以下でない
構文:
unless ( EXPR ) BLOCK { elsif (EXPR) BLOCK }* [ else BLOCK ]
unless にも任意個のelsif節と任意のelse節が後続可能です。
else if ⇒ elsif のような、else unless ⇒ elsunless はありません。
Perlの繰返し構文には、for,while, until,do-while, do-until,foreachと基本ブロックがあります。
forとforeachはシノニムの関係にありますが、ここではループカウンターを使ったC風の繰返し構文をfor、リスト・配列やハッシュの要素を対象にイテレートする構文をforeachとしました。
Perlには、Cのfor文風の繰返し構文があります。
[https://paiza.io/projects/uNiY129xVRqm9qvZEaRGag?language=perl コード例]:
use v5.12;
use warnings;
for (my $i = 0; $i < 5; $i++) {
    say "Hello $i"
}
say $i; # $i のスコープは for ループ内なのでここで参照すると、グローバル変数 $i の参照になります。
実行結果:
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
my $i = 0が評価され、レキシカルスコープのループ変数$iが初期化されます。
$i < 5が評価されます。真であれば BLOCK が実行され、文字列が出力されます。偽であればその時点でループを終了します。
$i++が評価され、$iの値が1増加します。
2と3を繰り返します。
構文:
[ LABEL ] for ( [ EXPR ]; [ EXPR ]; [ EXPR ] ) BLOCK
カッコの中に3つの式をコンマで区切って記述します。いずれも省略可能です。
最初のEXPRは初期化式です。ループの開始時に1回だけ評価されます。主にループ変数の初期化に使われます。
ここで my 宣言されたレキシカルスコープのループ変数のスコープはforループの中です。
次のEXPRは条件式です。BLOCKが実行される前に毎回評価され、偽となった時点でループは終了します。
条件式を省略した場合、真が仮定され無限ループとなります。
最後のEXPRは継続式です。BLOCKが実行された後に毎回評価されます。主にループ変数を変化させるのに使われます。
while文は、EXPRが真である限り、ブロックを実行し続けます。
for文の例と同等のものは次のようになります（厳密には $i のスコープがループを抜けた後も続くところが違います）。
[https://paiza.io/projects/oBw37zOlIRLcFXzY7L1paQ?language=perl 例]:
use v5.12;
use warnings;
my $i = 0;
while ($i < 5) {
    say "Hello $i";
    $i++;
}
実行結果:
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
continueブロックをfor文の継続式をイミュレーションできます。
例:
use v5.12;
use warnings;
my $i = 0;
while ($i < 5) {
    say "Hello $i";
}
continue {
    $i++;
}
実行結果:
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
構文:
[ LABEL ] while ( EXPR ) BLOCK [ continue BLOCK ]
whileは、EXPRが真である間BLOCKを繰り返し実行します。
untilは、EXPRが偽である限り、ブロックを実行し続けます。
for文の例と同等のものは次のようになります（厳密には $i のスコープがループを抜けた後も続くところが違います）。
例:
use v5.12;
use warnings;
my $i = 0;
until($i >= 5) {
    say "Hello $i";
    $i++;
}
実行結果:
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
continueブロックをfor文の継続式をイミュレーションできます。
例:
use v5.12;
use warnings;
my $i = 0;
until ($i => 5) {
    say "Hello $i";
}
continue {
    $i++;
}
実行結果:
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
構文:
[ LABEL ] until ( EXPR ) BLOCK [ continue BLOCK ]
untilは、EXPRが偽である間BLOCKを繰り返し実行します。
つまり、 while ( EXPR ) は until ( ''!'' EXPR ) と等価です。
doブロックにwhileが後置された場合は、まずdoブロックが一度実行されてから、whileの条件が真である間繰り返します。
doブロックはループではないので、後述する実行制御文を用いることはできません。LABELを付ける事も出来ません。
構文:
do BLOCK while ( EXPR ) ;
[https://paiza.io/projects/raWcnkYhPXCDVQJVZ9wg8w?language=perl 例]:
use v5.12;
use warnings;
my $i = 4;
do {
    say $i;
} while ($i--);
実行結果:
4
3
2
1 
0
上に構文と書きましたが、実際は EXPR1 while EXPR2 の EXPR1 が do BLOCK になった複合構文です。
doブロックにuntilが後置された場合は、まずdoブロックが一度実行されてから、untilの条件が偽である間繰り返します。
doブロックはループではないので、後述する実行制御文を用いることはできません。LABELを付ける事も出来ません。
構文:
do BLOCK until ( EXPR ) ;
[https://paiza.io/projects/vzTBfzbvBiHUZ3R89hdcKw?language=perl 例]:
use v5.12;
use warnings;
my $i = 4;
do {
    say $i;
} until ($i-- <= 0);
実行結果:
4
3
2
1 
0
上に構文と書きましたが、実際は EXPR1 while EXPR2 の EXPR1 が do BLOCK になった複合構文です。
構文:
[ LABEL ] foreach [ VAR ] ( LIST ) BLOCK [ continue BLOCK ] 
リストの値を順番にVARに代入し、BLOCKを実行します。
VARはループ内のlocal変数とみなされるので、プログラムの他の場所で使用していても問題ありません。
VARを省略した場合、local変数の$_が使われます。
foreach my $i ( 0..4 ) { say "Hello $i"; }
これもfor文の例と同等ですが、while文、until文の例と同様に厳密には等価ではありません。
foreachにもcontinueブロックを設けることが出来ます。
foreachはforのシノニムで、相互に置換えることが出来ます。
一行プログラム（ワンライナー）などでは、foreachとしてforを使うことがしばしばあります。
{ と } に囲まれた基本ブロック( ''Basic block'' )が、ループの節にあるのは奇異に感じるかもしれませんが、Perl では基本ブロックは「１周しかしないループ」で、ループ制御文を使うことができます。
doブロックは基本ブロックではなく、ブロックの最後の式の値を返す式です。
doブロックが式だからこそ、while 文修飾子 や until 文修飾子 とも結合できるのです（やる気になれば、if/until/foreach文修飾子とも結合できます）。
doブロックでは、ループ制御文を使うことはできません。
[https://paiza.io/projects/uOKdKk2oOzY-ZCaZf6Fskw?language=perl doブロックは式]:
use v5.12;
use warnings;
my $x = do { my $i = 100; $i+100 };
say $x
実行結果:
200
do と next の組合わせ:
do {{
  next if $x == $y;
  ...
 until $x++ > 0;
doブロックの {} の内側に、基本ブロックの {} を入れます。
do と last の組合わせ:
{
  do {
    last if $x == $y;
    ...
  } while $x++ <= 0
}
doブロックの {} の外側を、基本ブロックの {} で囲みます。
Perl 5.36.0 で、待望の defer が追加されました。
deferで登録されたブロックは、スコープを抜けたときに実行されます:
use v5.36.0;
use feature 'defer';
no warnings "experimental::defer";
say "Befor";
{
  defer{ say "One" }
  defer{ say "Two" }
  defer{ say "Three" }
  say "Done!"
}
say "After";
実行結果:
Befor
Done!
Three
Two
One
After
ブロックは、登録した逆順に実行されます。
色々な用途が考えられますが、open で開いたファイルハンドルの close 処理を defer で登録する使い方が真っ先に思いつきます。
Perlの真理値のルールはやや難解です。
数値:0は偽、それ以外は真。
文字列:""（空文字列）あるいは"0"（数値0に暗黙変換される）は偽、それ以外は真。
リスト:()（空リスト）は偽、それ以外は真（これはコンテキストにも影響され、スカラコンテキストにリストを渡すと要素数になり要素ゼロの場合、数値0と評価され偽となります）。
ハッシュ:要素数ゼロのハッシュは偽、それ以外は真（これはコンテキストにも影響され、スカラコンテキストにハッシュを渡すと要素数になり要素ゼロの場合、数値0と評価され偽となります）。
undef:偽
多くの説明では、数値にしか言及していませんが、他にも条件式で「偽」と評価される値があります。特に文字列には注意してください。
[https://paiza.io/projects/iHPvizrYCgiU7OGEblnqMg?language=perl Perlのコード例]:
my $x = 1;
if ($x) {
    print $x . 'は真';
} else {
    print $x . 'は偽';
}
結果:
1は真
[https://paiza.io/projects/1Uvsp06z6snskIqWPPNySw?language=perl 0の真理値]:
my $x = 0;
if ($x) { 
    print $x . 'は真'; 
} else { 
    print $x . 'は偽'; 
}
結果:
0は偽
''[https://paiza.io/projects/ihWh2eRbTWrtEdV7rVjUhw?language=perl （空文字列）や’0’も偽]'':
my @ary = (0, 1, 2, 3, '', "0", " ", "1", "2", (), (1), undef);
foreach my $x(@ary) {
    if ($x) {
        print "($x)は真 ";
    } else {
        print "($x)は偽 ";
    }
}
実行結果:
(0)は偽 (1)は真 (2)は真 (3)は真 ()は偽 (0)は偽 ( )は真 (1)は真 (2)は真 (1)は真 ()は偽 
Perl 5.36.0 からは use builtin qw(true false) で、真理値定数 true と false が定義されたので、constant プラグマを使った真理値定数の定義は Obsolate になりました。また、builtin::is_bool() も 5.36.0 で追加されました。
[TODO:節を改めての builtin の解説]
Perlには、他のいくつかのプログラミング言語にある、真理値定数 true と false がありませんが、constant プラグマを使うことで実現できます[https://perldoc.perl.org/constant constant - Perl pragma to declare constants
]。
[https://paiza.io/projects/EM7HVBT8AT-SRENk9s8O8A?language=perl constant プラグマを利用]:
use constant {
    false => 0 != 0,
    true  => 0 == 0
};
my @ary = (false, true);
foreach my $a(@ary){
    if ( $a ) { 
        print "($a)は真 ";
    } else { 
        print "($a)は偽 ";
    }
}
実行結果:
()は偽 (1)は真 
0 != 0 が 0 ではなく ”” というのは意外ですね。
次の制御構文は、文修飾子( ''Statement Modifiers'' )としても使用できます[https://perldoc.perl.org/perlsyn#Statement-Modifiers Statement Modifiers]。
構文:
EXPR if EXPR
EXPR unless EXPR
EXPR while EXPR
EXPR until EXPR
EXPR foreach [ VAR ] LIST
一文のみのごく簡単な制御の場合はこちらのほうが簡潔で、英文のような見た目になります。
修飾子が後になったほか、条件式を囲む括弧 ( ) が不要などの差異があります。
Perlの（文修飾子でない）制御構文には { } が必須なのですが、文修飾子では逆に使用不可です。
Cになれた人には、単文・複文の関係にみえますが、Perlの構文は、文:=単文 | 複文 ではなく制御構文ごとにブロックを要求したり式を要求したりします。
条件文:
print "Good morning.\n" if 6 <= $hour and $hour < 12;
繰返し文:
print "@{[$i++]} " while $i < 10;
print "<$_> " foreach qw(abc def xyz);
print "\n----\n";
$i = 0;
while ($i < 10) {
    print "@{[$i++]} "
}
foreach (qw(abc def xyz)) {
    print "<$_> ";
}
実行結果:
0 1 2 3 4 5 6 7 8 9    
----
0 1 2 3 4 5 6 7 8 9   
ループ制御を行なう実行制御文の説明をしたいと思います。
前出のdo-while以外のループ構文と空のブロックでは、ループの挙動を制御する各種実行制御文が使用出来ます（doブロックでループ制御文を使いたい場合、基本ブロックを併用します）。
例外として、continue BLOCK 中でそれらの実行制御文を使用した場合には、直近のループブロックを制御する振舞いをします。
ラベルを指定することで入れ子になったループの制御もできます。省略した場合、もっとも内側にあるループを指定したとみなされます。
即座にループから脱出します。continueブロックは実行されません。
OUTER: while ( 1 ) { #無限ループ
   $i = 0;
   INNER: while ( $input = <> ) {
       last       if $input =~ /^restart/; # 直近のINNERループを脱出
       last OUTER if $input =~ /^quit/;    # 明示されたOUTERループを脱出
       print "$i\n";
   } continue {
       $i++;
   }
}
残りの文をスキップし、次の反復に移ります。
ループ条件式は評価されます。continueブロック、for文の継続式も評価されます。
残りの文をスキップし、反復をやりなおします。
ループ条件式は評価されません。continueブロック、for文の継続式も評価されません。
continueブロック中の制御の例を上げます。
my $i = 0;
{                        #1.
    print "OUTER\n";
    {                    #2.
        $i ++ ;
        print "INNER\n" ;
    } continue {
        redo if $i < 10 ;
        print "$i\n"
    }
}
この場合のredoは#1のブロックではなく、直近の#2ブロックを制御する振舞いをします。