我有一个子例程,它在一个eval
表达式中处理一种格式。如果这个子例程被调用多次,perl 会警告格式已被重新定义。
此代码:
use warnings;
routine();
routine();
sub routine{
my $s = "FAIL";
my $def = "format =n@<<<<@>>>>n$s, $sn.";
eval $def;
write;
}
指纹
FAIL FAIL
Format STDOUT redefined at (eval 2) line 1.
FAIL FAIL
是否可以删除子例程末尾的格式声明?
这是一个使用标志来避免重新定义格式的简单解决方案。
use strict;
use warnings;
routine();
routine();
my $format_defined;
sub routine{
my $s = "FAIL";
if (!$format_defined) {
my $def = "format =n@<<<<@>>>>n$s, $sn.";
eval $def;
$format_defined = 1;
}
write;
}
这是一个更复杂的解决方案,允许为每个调用重新定义格式。它使用临时文件句柄代替 STDOUT,将输出重定向到标量,然后您可以将其打印到 STDOUT。
routine('FAIL');
routine('PASS');
sub routine{
my $s = shift;
format REPORT =
@<<<<@>>>>
$s, $s
.
my $report;
open my $fh, '>', $report;
select $fh;
$~ = 'REPORT';
write;
close $fh;
select STDOUT;
print $report;
}
十年后,我遇到了同样的问题,并意识到让格式足够灵活地工作并不容易。@stevenl提到的解决方案不是那么有效,因为将 eval 限制为仅第一次出现,结果重复格式与第一次评估变量。所以我有很好的表格,与第一条记录的数据相同。第二种解决方案不实现 eval,因此无法动态构建格式定义。
我应用的解决方法只是:
no warnings qw/redefine/;
在子例程的主体内部.
是的,我知道,丑陋但有效。仍在寻找更好的解决方案:)