語彙とパッケージの変数が混在しています。あなたのプログラムがuse strict
とuse warnings
の場合、これはかなり明らかです。
my
で変数を宣言しないと、Perlは変数をパッケージ変数とみなします。プログラムのすべての部分から(同じ名前空間内に)表示されます。
my
で変数を宣言すると、という語彙になります。それはそれだけで範囲内に存在することを意味しそれで作成しました。
my $foo = 1; #
#
if ($foo) { # #
my $bar = 2; # #
} # #
^^
| | scope that $foo exists in
| scope that $bar exists in
同じことがここで起こっています。
あなたは1st
サブ内"cat asdf"
に(::
がmain
名前空間である)パッケージ変数$::cmd
を設定しています。次に2nd
というサブフォルダを呼び出し、else
ブランチに入ります。その範囲では、新しい字句$cmd
が作成されます。それはプログラムのその部分でのみ有効です。その後、out_log()
に渡され、おそらくそれが印刷されます。その後、"cat asdf"
の値をout_log()
に設定して$::cmd
を渡します。その時点で新しい$cmd
はもう存在しません。あなたのプログラムでuse strict
を持っていた場合、デフォルトのパッケージ変数の挙動が、その場合にはオフになっているので、あなたは、変数を定義する必要がありますので
![code with freehand lines](https://i.stack.imgur.com/0Up3s.png)
、プログラムは、まったく動作しません。
実際には、パッケージ変数で操作するのではなく、引数を関数に渡すべきです。
それに加えて、あなたのプログラムではうまくいかないことがいくつかあります。 3つの引数open
と字句ファイルハンドルを使用し、戻り値がopen
であることを確認する必要があります。
機能名は数字で始めることができないので、1st
と2nd
は有効な名前ではありません。彼らがやっていることや表現したことの後で物事に名前を付ける方がいいです。これにより、後でプログラムを読みやすくなります。
完全なプログラムはそのように見えます。
use strict;
use warnings;
my ($code, $reg, $annotation); # these values come from somewhere...
run_cmd(compose_cmd(), $code, $reg, $annotation);
sub compose_cmd {
return "cat asdf";
}
sub run_cmd {
my ($cmd, $code, $reg, $annotation) = @_;
if ($code =~ /aa/) {
my $cmd = "$reg $annotation";
out_log($cmd);
}
else {
my $cmd = "$reg $annotation";
out_log($cmd);
}
out_log("$cmd");
open my $fh, '<', $cmd or die $!;
# do stuff with $fh ...
}
sub out_log {
print @_;
}
実際には、サブは数字で始めることはできません。 – simbabque