防止perl打印相同的警告消息

时间:2012-03-19 11:42:16

标签: perl warnings

以下面的无意义脚本为例:

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只打印一次相同的警告,它可能会更方便。

1 个答案:

答案 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}++;
    };
}

然后你决定了一些事情。