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

Mat*_*eck 10 perl warnings

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

use strict;
use warnings;

my $uninitialisedValue;

while(<>){
  print ${$uninitialisedValue}{$_},"\n";
}
Run Code Online (Sandbox Code Playgroud)

哪个从命令行运行:

$ perl warningPrinter.pl < longfile.txt
Run Code Online (Sandbox Code Playgroud)

无论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.
...
Run Code Online (Sandbox Code Playgroud)

我使用非常长的文件,所以在测试我的脚本时接收它作为输出至少是有点刺激性的.该过程可能需要一段时间才能响应CTRL-c终止信号,并且我的终端突然充满了相同的错误消息.

有没有办法让perl只打印一个相同且重复出现的警告消息的第一个实例,或者仅仅为执行脚本制作致命的警告消息?虽然我从来没有制作过一个尽管有警告的脚本,我也会接受.但是如果我能让perl只打印一次相同的警告,它可能会更方便.

Axe*_*man 10

我想我会告诉你如何创建独特的警告逻辑.我不推荐它:

my %printed;
local $SIG{__WARN__} = sub { 
    my $message = shift;
    my ( $msg, $loc ) = $message =~ m/(.*?) at (.*?line \d+)/;
    print $message unless $printed{$loc}{$msg}++;
};
Run Code Online (Sandbox Code Playgroud)

我应该说我不建议将其作为一般做法.因为最好有一个警告政策.它可以是可以采用未定义值的操作,也可以是您不想处理undef值.我尝试从已完成的代码中删除所有警告.

在第一种情况下,将no warnings 'uninitialized';for循环是一个容易得多-并且经常做的事情.在第二种情况下,您可能想要失败.

但是,如果它实际上是你想要处理的东西,但是曾经发出警告,比如你想要对数据进行可靠的处理,但是想要警告上游进程你得到了一些不好的数据,你可以去创建一个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}++;
    };
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

while ( <> ) { 
    warn_once( '$uninitialisedValue is uninitialized' )
        unless defined( $uninitialisedValue)
        ;
    no warnings 'uninitialized';
    print ${$uninitialisedValue}{$_},"\n";
}
Run Code Online (Sandbox Code Playgroud)

然后你决定了一些事情.

  • 请注意,除了关于考虑输入块的行号的部分之外,`diagnostics`模块执行所有这些操作. (2认同)