■制御構造としてのand,or
8.6で書いた
unless ($argn == 3){
die "argument must be three\n".
"usage : rep filter old_extention new_extention\n";
}
の部分は次のように書き換えることができる
($argn == 3) or die "argument must be three\n".
"usage : rep filter old_extention new_extention\n";
}
説明
or というのはその前の式を評価して、「そこで真だったら、その後に結合しているものを飛ばして先に行く」という性質を持っている。
この場合には「$argn」が真であれば、その後のdieを飛ばして先に進む。
一方、条件が偽だったら、orの後ろにある文を評価しに行く。この場合にはdieでプログラム自体が止まる。
これは、条件式を評価するorが、制御文として使えることを示している。
「プログラム言語として読むとその内容は自明ではないが、自然言語として読むとよくわかる」
dont move, or die:動いたら殺すぞ(うごくな、さもなくば死か)
のように、
($argn == 3) or die :$argnが3で無ければdie
と解釈。
エラーチェックなどによく使われる。
同様に
if (`which $filter` =~ /^no /){
die "filter \"$filter\" not found\n".
"usage :rep filter old_extention new_extention\n";
}
は
(`which $filter` =~ /^no /) and die "filter \"$filter\" not found\n".
"usage :rep filter old_extention new_extention\n";
と書くことができる。
and は or とは逆に左側に書いてあるものが偽であったら、その時点で右側の文をあきらめて先に進む。
(条件が正しければ、右側の文を評価する)
以上を踏まえ、プログラムrepは以下のように記述することができる。
$argn = ($filter,$oldext,$newext) = @ARGV; #@argvは引数が入る関数
($argn == 3) or die "argument must be three\n".
"usage : rep filter old_extention new_extention\n";
@files = glob("*.$oldext"); #oldextに該当する拡張子を持つファイル名を配列として@filesに格納
(@files + 0 ) or die "extention \"$oldext \" no match\n;.
"usage: rep filter old_extention new_extention\n";
(`which $filter` =~ /^no /)and die "filter \"$filter\" not found\n".
"usage :rep filter old_extention new_extention\n";
foreach(@files){
/(.*)\.$oldext/;
print("$filter < $1.$oldext > $1.$newext &\n");
system("$filter < $1.$oldext > $1.$newext &");
}
■サブルーチンの活用
dieのときに「usage」(使用法)を3回も連呼している。
このusageの呼び出しをサブルーチンにする。
$argn = ($filter,$oldext,$newext) = @ARGV; #@argvは引数が入る関数
($argn == 3) or &bye("argument must be three\n"); #$argnが3であれば以降は無視
@files = glob("*.$oldext"); #oldextに該当する拡張子を持つファイル名を配列として@filesに格納
(@files + 0 ) or &bye ("extention \"$oldext \" no match\n); #@filesが0であれば、以降は無視。
(`which $filter` =~ /^no /) and &bye ("filter \"$filter\" not found\n"); #fileterがない場合
#(`which $filter` =~ /^no /)が真なら以降を実施。
foreach(@files){ #oldextの拡張子を持つものがあれば以降を実施
/(.*)\.$oldext/; #正規表現でoldextの拡張子を持つもの
system("$filter < $1.$oldext > $1.$newext &"); #
}
sub bye{
my($msg) = @_;
print $msg;
die "usage :rep filter old_extention new_extention\n";"
}