Perl では,未定義値・数値の 0・文字列の "0"・空の文字列 "" は「偽」,その他は「真」と判断される。
数値の 0 | 0.0 なども数値としては 0 と同じなので,0.0 も偽となる。 |
文字列の "0" | "0.0" は文字列としては "0" とは異なるので "0.0" は真となる。 |
空の文字列 | 値が定義されていないのではなく,値が空の文字列であるということ。未定義値との違いに注意。 |
未定義値 | 値が定義されていないもの,あるいは undef によって未定義値とされたもの。 |
if, while などの条件の指定に式や変数などを書いた場合,真偽 (成立・不成立) は,その条件を評価したときに返される値 (返り値,戻り値) により決まる。例えば,m 演算子を用いてマッチングを行うと,成功すれば真 (1) を,失敗すれば偽 ("") を返す。s 演算子の場合は,置換に成功すれば置換した数を返すので,置換に成功すれば真 (1, 2, 3, ...) となり,成功しなければ偽 ("") となる。
上の説明は,スカラーコンテキストでの話。コンテキストについては Lesson 7 で説明する。
次のスクリプトの条件部分 (1) を変えて,どのようなものが真と判断され,どのようなものが偽と判断されるか確認しなさい。(else については,ここを参照。)
% perl -e 'if (1) { print "TRUE\n"; } else { print "FALSE\n"; }' 1. 0 10. "John" 2. 0.0 11. $var 3. "0.0" 12. undef 4. "" 13. length "John" 5. " " 14. length "" 6. "\n" 15. $var = "John" 7. 1 - 1 16. $var = "" 8. "1 - 1" 9. 0.5
Perl では,各データは数値としての値と文字列としての値を持つ。"4.0" と "4" は数値としては等しいが,文字列としては等しくない。データを比較するには,数値として比較するのか,文字列として比較するのかを区別し,それぞれに対して異なる演算子を用いなければならない。
数値 文字列 返り値 A は B と等しい A == B A eq B 成立すれば 1,
しなければ偽 ("")A は B と等しくない A != B A ne B A は B より大きい A > B A gt B A は B 以上 A >= B A ge B A は B より小さい A < B A lt B A は B 以下 A <= B A le B A と B を比較 A <=> B A cmp B A が B より
大きければ 1,
小さければ -1,
等しければ 0
文字列の大小の比較は文字コード上の順序を基に行う。文字コード上,後ろにあるものが前にあるものより大きい。大文字はすべて小文字よりも前に配列されているので,Z は a より「小さい」。大文字小文字を区別せずに比較するには,lc, uc などを使い,どちらかに揃えてから比較する。
if (lc "ABC" eq lc "abc") { ... } if (uc $var1 cmp uc $var2) { ... }
== と = は間違いやすいので気をつけること。
== は左辺と右辺を比較し,数値として等しければ真 (1),等しくなければ偽 ("") を返す演算子。
= は右辺の値を左辺の変数に代入する演算子で,代入した値が返り値となる。空の文字列と 0 (数値としての 0,あるいは文字列の "0") が代入された場合を除き,真となるため,while の条件を指定する際に,== と間違えて = を使うと,無限ループを作ってしまうので要注意。
A eq B と A =~ /B/ も混乱しやすいので,違いを確認しておくこと。
"abc" eq "a" 偽 "abc" ne "a" 真 "abc" =~ /a/ 真 "abc" !~ /a/ 偽 "abc" =~ /^a$/ 偽 "abc" !~ /^a$/ 真
and (&&), or (||), not (!) は,それぞれ「論理積」「論理和」「否定」の演算子である。
A and B は,A・B ともに真のとき真,それ以外は偽となる。A or B は A・B のどちらかが真であれば真,ともに偽のときに偽となる。not A は A が真のとき偽,偽のとき真となる。
A | B | A and B | A or B | not A |
真 | 真 | 真 | 真 | 偽 |
真 | 偽 | 偽 | 真 | 偽 |
偽 | 真 | 偽 | 真 | 真 |
偽 | 偽 | 偽 | 偽 | 真 |
これら論理演算子を使って複数の条件を組み合わせることで,複雑な条件が指定できるようになる。
and と &&,or と ||,not と ! には優先順序の違いがある。どちらも,後者の方が優先順序が高い。
優先順位が不明な場合には,( ) で括って結合の順番を明示的に指定するとよい。下の 1 と 2 は ( ) の付け方が違うだけだが,表わしていることは異なる。
1. (A or B) and (C or D) 2. A or (B and C) or D
A or B はどちらか一方が真ならば真となる。Perl では,A が真であれば B の真偽に関係なく A or B が真となるため,B の評価を行わない。これを利用して,A が成立しなかったときだけ B を行うのに or, || が使われることがある。
#ファイルを開く。開けなければスクリプトを終了する。 open (IN, "input.txt") or die "Cannot open the file\n"
open は成功すると真を,失敗すると偽を返す。die は引数で指定したエラーメッセージを表示してスクリプトを終了する関数。引数は省略可。
次のように書くと,変数 $var の値が未定義・数値の 0・文字列の "0"・空の文字列 "" の場合,50 が代入される。例えば,値が指定されなかったときのデフォルトを指定するのに使える。(演算子の優先順位の関係で,二つ目のものには ( ) が使われている。)
$var or $var = 50 $var || ($var = 50) cf. $var = 50 if ! $var; $var = 50 unless $var;
$var || ($var = 50) は次のように書くこともできる。
$var ||= 50
・A and B
A and B の場合は両方とも真でなければ真とはならないので,A が偽であれば,B の評価を行わない。これを利用して,A が成立したときだけ B を行うのに and, && が使われる。
#ファイルを開く。開ければ1レコード $data に読み込む open (IN, "input.txt") and $data = <IN>
これまで学んだ関数・演算子には,length, lc, substr のように対象自体は何の変化も受けず,関数・演算子が返す値を利用するものと,chop, chomp, s/// などのように対象に対して何らかの作用を及ぼすものとがあった。
chop, chomp, s/// などの関数・演算子は,対象に対してある操作をする。したがって,単に次のように書けば,対象が変化する。
chop $str; chomp $str; $str =~ s/Japan/<<$&>>/g;
副作用として返り値を返すので,それを利用したければ,変数に代入するなどの処理をする。
$var = chop $str; #$var には削除された文字が代入される $var = $str =~ s/Japan/<<$&>>/g; #$var には置換の回数が代入される
これに対し,length, lc, substr などは,ある値を返すのが主作用で,引数として指定された対象そのものは変化を受けない。したがって,次の処理は (それだけでは) 無意味な処理である。
length $str; lc $str; substr ($str, -25);
返す値を利用するために使う関数なので,返り値を変数に代入したり,何かと比較したりなど,値を返すことに意味がある文脈で使う。
$var = length $str; #$str の文字数を $var に代入 if (1 <= length $str) { ... } #$str に何か文字があれば処理を行う if (length $str) { ... } #$str 〃 print length $str; #$str の文字数を出力する
lc は「対象文字列を小文字に変換した文字列を返す」関数である。これを誤って「対象文字列を小文字にする」関数と考えてしまうと,lc $str としただけで,$str の内容が小文字に変換されたような錯覚に陥るので注意すること。$str の内容を書き換えるには次のようにする。
$str = lc $str; $str =~ tr/A-Z/a-z/;