- Perl ›
- here
if文による条件分岐
プログラミングを書いていると条件によって処理を変えたり、同じ処理を繰り返したくなる場合があります。
そのような場合はif文やfor文を使うことによって条件分岐と繰り返しを実現できます。
条件分岐の基礎
条件分岐の基礎を解説します。
if文
Perlで条件分岐を行うにはif文を使用します。まず最初に簡単な条件分岐を書いてみます。変数の値が「5」の場合に「OK」と出力するif文です。
my $num = 5; if ($num == 5) { print "OK\n"; }
if文は以下のような構文です。条件が真になったときに、続くブロックの中が実行されます。
if (条件) { ...; }
==は比較演算子で、数値が等しい場合に真を返します。
この例の場合は、変数には5が入っているので「$num == 5」は真を返します。
そして、条件が真なので、続くブロックの中身が実行されます。
変数の内容を「4」などに変えてみると「OK」と表示されないことも確認してみてください。
if~else文
if~else文を使うと、条件が真の場合に実行する処理と偽の場合に実行する処理を書くことができます。
# if文 my $num = 5; if ($num == 5) { print "OK\n"; } else { print "Not OK\n"; }
if~elsif文
if~elsif文を使うと、条件を複数記述することができます。
# if~elsif my $num = 5; if ($num == 5) { print "Number is 5\n"; } elsif ($num == 7) { print "Number is 7\n"; }
上記の場合は「$num」が5だった場合は「Number is 5」、「$num」が7だった場合は「Number is 7」と表示されます。
C言語やJavaでは「else if」ですが、Perlでは「elsif」となっていることに注意してください。
elsifは複数指定することもできます。
# 複数のelsif my $num = 5; if ($num == 5) { print "Number is 5\n"; } elsif ($num == 7) { print "Number is 7\n"; } elsif ($num == 9) { print "Number is 9\n"; }
elsifはelseと組み合わせて利用することもできます。elseは必ず最後に記述します。
# elseifとelseの組み合わせ my $num = 5; if ($num == 5) { print "Number is 5\n"; } elsif ($num == 7) { print "Number is 7\n"; } elsif ($num == 9) { print "Number is 9\n"; } else { print "Not match\n"; }
比較演算子
if文の条件の中で「==」という記号を使いましたが、これは比較演算子の一つです。
Perlの比較演算子をここで紹介しておきます。Perlには二種類の比較演算子があります。数値比較演算子と文字列比較演算子です。
数値比較演算子
数値比較演算子は、値を数値として比較するときに利用する演算子です。
演算子 | 意味 |
---|---|
A == B | AとBは等しい |
A != B | AとBは等しくない |
A > B | AはBより大きい |
A >= B | AはB以上 |
A < B | AはBより小さい |
A <= B | AはB以下 |
文字列比較演算子
文字列比較演算子は、文字列を辞書順で比較するときに利用する演算子です。
演算子 | 意味 |
---|---|
A eq B | AとBは等しい |
A ne B | AとBは等しくない |
A gt B | AはBより大きい |
A ge B | AはB以上 |
A lt B | AはBより小さい |
A le B | AはB以下 |
数値比較と文字列比較
Perlでは、値を数値として比較したい場合は数値比較演算子を使い、文字列として比較したい場合は文字列比較演算子を使います。
この点が他の言語と異なる部分なので注意してください。
# 数値比較 my $num = 4; if ($num < 6) { ... } # 文字列比較 my $animal = 'Cat': if ($animal eq 'Dog') { ... }
文字列比較演算子には、大きさを比べるための「gt」「ge」「lt」「le」がありますが、これは辞書順で比較されます。
たとえば「1」と「03」を数値比較した場合は「1」は「1」、「03」は「3」と解釈され「03」の方が大きいです。
けれども「1」と「03」を文字列比較した場合は、最初の文字から判定され「1」と「0」は、文字コードが「1」のほうが大きいので「1」のほうが大きくなります。
my $num1 = '1'; my $num2 = '03'; # 数値比較 if ($num1 > $num2) { # 実行されない print "OK 1\n"; } # 文字列比較 if ($num1 gt $num2) { # 実行される print "OK 2\n"; }
Perlの比較演算子の詳しい解説については以下をご覧ください。
Perlの真偽値
次にPerlの真偽値についてきちんと理解しておきましょう。if文では、条件が真になったときにブロックの中が実行されましたね。偽になったときは実行されませんでした。
ここでPerlでの真偽値について、正しく理解しておきましょう。
Perlで偽とされる値
Perlで偽とされる値は以下の4つです。
1 | undef | 未定義値 |
2 | "" | 空文字列 |
3 | 0 | 0 |
4 | "0" | 文字列の0 |
以下のようにif文の条件が偽値の場合は、ブロックの中が実行されません。
# 条件が偽の場合は実行されない if (undef) { # 実行されない } if ("") { # 実行されない } if (0) { # 実行されない } if ("0") { # 実行されない }
Perlで真とされる値
上記で偽とされるもの以外は、すべて真になります。たとえば例を挙げると次のものが真になります。
長さのある文字列
"Cat"
0以外の数値
13 -3 1.5
"0"以外の数値を含む文字列
"13" "0.1" "0.0"
リファレンスあるいはオブジェクト
my $nums = [1, 2, 3]; my $scores = {}; my $object = XML::Simple->new;
「"0.0"」という文字列が真になることに注意してください。
要素を持つリスト
(0) (1, 2);
以下のようにif文の条件が真の場合は、ブロックの中が実行されます。
# 条件が真の場合は実行される if ("Cat") { # 実行される } if (13) { # 実行される } if ("13") { # 実行される } my $object = XML::Simple->new; if ($object) { # 実行される }
配列をif文の条件に書く場合
配列をif文に書くというのはよくあることなので、真偽値としてどう評価されるのかを見ておきましょう。
配列が要素を持つ場合は、スカラコンテキストで評価され、配列の個数が評価されます。
配列が要素を持つ場合は、ifブロックが実行され、そうでない場合は、実行されません。
my @nums = (1, 2); if (@nums) { # 実行される } my @nums = (); if (@nums) { # 実行されない }
Perlの真偽値の詳細については以下をご覧ください。
Perlの論理演算子
次に「AかつB」「AまたはB」「Aではない」ということを表現できる論理演算子を解説します。
これまでは、単一の条件だけを見てきましたが、論理演算子を使うことによって複合的な条件や否定を表現することができます。
演算子 | 意味 |
---|---|
|| | 論理和 |
&& | 論理積 |
! | 否定 |
or | 論理和(&&より優先順位が低い) |
and | 論理積&&より優先順位が低い) |
not | 否定(!より優先優位が低い) |
論理積(A かつ B)
たとえば変数「$num」が「1より大きい、かつ、5より小さい」という条件を表現するには&&を使って次のように書きます。
if ($num > 1 && $num < 5) { ... }
andも同じ意味を持ちますが演算子の優先順位が低く、if文の条件部で書く場合は「&&」を使うのが慣習的なPerlの書き方となっています。
論理和(A または B)
次に、変数「$num」が「1より小さい、あるいは、5より大きい」という条件を表現するには||を使って次のように書きます。
if ($num < 1 || $num > 5) { ... }
orも同じ意味を持ちますが演算子の優先順位が低く、if文の条件部で書く場合は「||」を使うのが慣習的なPerlの書き方となっています。
否定(Aではない)
変数「$num」が「真ではない」という条件を表現するには!を使って次のように書けます。
if (!$num)) { ... }
notも同じ意味を持ちますが演算子の優先順位が低く、ソースコードで利用されることは少ないようです。
論理演算子を組み合わせて使う
論理演算子は組み合わせて使うことができます。括弧を使うことで演算子の結合順序を制御することができます。
if ($num > 10 || (($num > -3 && $num < 6) && !($num == 0))) { ... }
「&&」の結合順序のほうが「||」の結合順序より高く、途中の一部の括弧はプログラム的には意味がありませんが、ソースコードをわかりやすくするために、意味の区切りで、積極的に「()」を使いましょう。
論理演算子の詳細な解説については以下の記事を参考にしてください。
やや特殊な条件分岐
Perlでしばしば使われるやや特殊な条件分岐について解説します。
unless文
unless文はif文で条件を否定した場合と同じ処理を書くことができます。
# $numが真でなければブロックを実行 unless ($num) { ... }
次のif文と全く同じ意味になります。
if (!$num) { ... }
意味が同じならunless文はどういうときに使うんでしょうか。それは「でなければ」という気持ちを強めたいときです。unlessの方が「でなければ」という気持ちが目立ちます。
たとえばエラーチェックの処理が主要な処理なのであれば、以下のように書くと「if」と「!」を使って書くより目立ちますね。define関数を使って値が定義されなかった場合にブロックを実行する処理です。
unless (defined $num) { ... }
失敗した処理における分岐をorで書く
Perlには論理演算子 orを使った条件分岐の処理が慣習的に書かれることが多いです。
典型的な例では、open関数が失敗した場合のエラー処理には「or」が出てきます。
open関数が失敗して偽値が返された場合に、「or」の後ろの処理が実行されます。
open(my $fh, "<", $file) or die "Can't open $file:$!";
主要な処理を先に書いて、補助的なエラー処理をorを使って、後ろ側に書いています。こんな風に自然言語のような表現でプログラミングが書けるのもPerlの面白いところのひとつです。
後置のifと後置のunless
Perlではなんとifとunlessを、処理の後ろに記述することができます。
# 後置のif $num1 = 1 if !defined $num1; # 後置のunless $num2 = 1 unless defined $num2;
1行で書ける条件分岐であれば、後置のif、unlessを使って書くこともできます。
後置のifとunlessの最大のメリットは、通常のifとunlessと違って、スコープを作成しないので、その分処理が速いということです。通常は意識する必要はありませんが、速度をどうしても稼ぎたいときには、少し早くなります。
for my $num (@nums) { last if !defined $num; } for my $num (@nums) { next if !defined $num; }
三項演算子
Perlには三項演算子と呼ばれる演算子があります。
三項演算子を使うと、条件によって、返却する値を変えることができます。
# 三項演算子の構文 条件 ? 値1 : 値2
条件が真の場合は、値1が返り、偽の場合は値2が返ります。
以下の例では「$flag」が真の場合に「$animal」に「Cat」が代入され、偽の場合に「$animal」に「Dog」が代入されます。
my $flag = 1; # 3項演算子 my $animal = $flag ? 'Cat' : 'Dog';
ifを使った条件分岐でも、同じことができますが、三項演算子を使うと簡潔に書けます。
三項演算子を複数重ねて使う
三項演算子は複数重ねて使うことができ、「if ~ elsif ~ else」に該当する書き方ができます。
my $flag = 2; my $animal = $flag == 0 ? 'Cat' : $flag == 1 ? 'Dog' : $flag == 2 ? 'Mouse' : 'Cow';
「$flag」が「2」なので「$animal」には「Mouse」が代入されます。三項演算子を重ねて使うときは、見やすいように複数行にして書くのがお勧めです。
特殊な代入演算子「||=」「//=」でデフォルト値を設定
Perlにはよく使われるデフォルト値の設定方法があります。それは特殊な代入演算子である「||=」あるいは「//=」を使う方法です。
# もし「$x」が偽ならば「$x」に5を設定 $x ||= 5; # もし「$x」が未定義であれば「$y」に7を設定 $y //= 7;
「A ||= B」は、「A」が偽であれば「A」に「B」の内容が代入されます。
「A //= B」は、「A」が未定義であれば「A」に「B」の内容が代入されます。
「A //= B」の構文はPerl 5.10で導入されたので、Perl 5.10以降であれば「A //= B」が使用できます。「A ||= B」はバグを生みやすいので、こちらを使用するのがお勧めです。たとえば「A ||= B」だと「A」が「0」の場合に、デフォルト値が設定されてしまいます。
頻繁に使う構文なので覚えてしましょう。
繰り返し文
繰り返し文については以下の記事を参考にしてください。