几乎每个编写的perl程序都使用这个习语:
{
open(my $fh, '>>', $filename) || die "you lose";
print $fh $blah;
}
然而,我不想死,我想跳过印刷品。 所以我写道:
{
print "you lose\n" unless (open(my $fh, '>>', $filename) and print $fh $blah);
}
并获取“不能使用未定义的值作为./o.pl第5行的符号引用”。
删除my(错误表单)会消除此错误,如下所示:
{
my $fh;
print "you lose\n" unless (open($fh, '>>', $filename) and print $fh $blah);
}
但为什么?
为什么在破损的代码中,$fh
不会open(my $fh...
存在到块的结尾(}
)?
答案 0 :(得分:10)
my
在语句结束前不生效。
出于同样的原因,my $x = $x
将不会在声明的右侧看到新的$x
。它会看到旧的$x
。
例如
use strict;
use warnings;
my $x = 42;
{
my $x = $x + 1;
print "inside, x = $x\n";
}
print "outside, x = $x\n";
打印:
inside, x = 43
outside, x = 42
您的open
语句大致相当于上面的内部my
语句。如果您在外部范围内声明$fh
,则会发生令人惊讶的乐趣:您可能最终打印到错误的文件。
答案 1 :(得分:5)
您可能更喜欢
{
open(my $fh, '>>', $filename) || warn "you lose";
print $fh $blah if $fh->opened;
}
当然,如果您愿意,也可以删除warn
。
如果您的Perl 5早于版本14,那么您需要添加
use IO::File
到代码的标题。
答案 2 :(得分:4)
如果您在程序中添加strict
和warnings
,则会收到更多有用的错误消息:
use strict;
use warnings;
{
my $filename = "test.txt";
print "you lose\n" unless (open(my $fh, '>>', $filename)
and print {$fh} $blah);
}
__END__
Global symbol "$fh" requires explicit package name at test.pl line 6.
Global symbol "$blah" requires explicit package name at test.pl line 6.
Execution of test.pl aborted due to compilation errors.
问题在于您无法在同一语句中声明和使用词法变量。 $fh
只有在上有open
的行后才可用。
答案 3 :(得分:3)
您不能声明词法变量并在同一语句中使用它。
但你可以,
open($_, '>>', $filename) and print $_ $blah for my $fh;
或
open($_, '>>', $filename) ? print $_ $blah : print "you lose\n"
for my $fh;