以下面的无意义脚本为例:
use strict;
use warnings;
my $uninitialisedValue;
while(<>){
print ${$uninitialisedValue}{$_},"\n";
}
从命令行运行:
$ perl warningPrinter.pl < longfile.txt
无论STDIN包含什么,STDOUT都将充满:
Use of uninitialized value in print at warningPrinter.pl line 16, <> line 1.
Use of uninitialized value in print at warningPrinter.pl line 16, <> line 2.
Use of uninitialized value in print at warningPrinter.pl line 16, <> line 3.
Use of uninitialized value in print at warningPrinter.pl line 16, <> line 4.
...
我使用很长的文件,所以在测试我的脚本时接收它作为输出至少是轻微的烦恼。该过程可能需要一段时间才能响应CTRL-c终止信号,并且我的终端突然收到相同的错误消息。
有没有办法让perl只打印相同且重复出现的警告消息的第一个实例,或者仅仅为执行脚本制作致命的警告消息?虽然我从来没有制作过一个尽管有警告的脚本,我也会接受。但是如果我能让perl只打印一次相同的警告,它可能会更方便。
答案 0 :(得分:10)
我想我会告诉你如何创建独特的警告逻辑。我不推荐它:
my %printed;
local $SIG{__WARN__} = sub {
my $message = shift;
my ( $msg, $loc ) = $message =~ m/(.*?) at (.*?line \d+)/;
print $message unless $printed{$loc}{$msg}++;
};
我应该说我不建议将其作为一般练习。因为最好有一个警告政策。它可以是一个可以取未定义值的操作,也可以不想处理undef
值。我尝试从已完成的代码中删除所有警告。
在第一种情况下,将no warnings 'uninitialized';
置于for
循环中会更容易 - 并且常规要做的事情。在第二种情况下,您可能想要失败。
但是,如果它实际上是你想要处理的东西,但是曾经发出警告,比如你想要强大的数据处理,但是想要警告上游进程你得到了一些不好的数据,你可以去创建一个{ {1}}:
sub warn_once
并称之为:
{ use Carp ();
my %warned;
sub warn_once {
my $message = shift;
my ( $msg, $loc ) = $message =~ m/(.*?) at (.*?line \d+)/;
Carp::carp( $message ) unless $warned{$loc}{$msg}++;
};
}
然后你决定了一些事情。