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

时间:2021-09-22 09:51:59

Consider the following nonsense script as an example:

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

use strict;
use warnings;

my $uninitialisedValue;

while(<>){
  print ${$uninitialisedValue}{$_},"\n";
}

Which is run from the command line:

哪个从命令行运行:

$ perl warningPrinter.pl < longfile.txt

Regardless of what STDIN contains, the STDOUT will be full of:

无论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.
...

I work with very long files, so receiving this as output when testing my script is at the very least mildly irritating. It can take a while for the process to respond to a CTRL-c termination signal and my terminal is suddenly filled with the same error message.

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

Is there a way of either getting perl to print just the first instance of an identical and reoccurring warning message, or to just make warning messages fatal to the execution of the script? Seeing as I have never produced a script that works despite having warnings in them, I would accept either. But its probably more convenient if I can get perl to print identical warnings just once.

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

1 个解决方案

#1


10  

I thought I would show you how unique warning logic might be created. I don't recommend it though:

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

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

I should say that I do not recommend this as a general practice. Because it's better to have a warning policy. It's either an operation that can take an undefined value, or you don't want to handle an undef value. I try to remove all warnings from my completed code.

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

In the first case, putting no warnings 'uninitialized'; in the for loop is a much easier--and regular thing to do. In the second case, you'd probably want to fail.

在第一种情况下,没有警告“未初始化”;在for循环中是一个更容易 - 而且常规的事情。在第二种情况下,您可能想要失败。

However, if it is something you would actually like to handle but warn once about, say that you wanted robust handling of the data, but wanted to warn upstream processes that you got some bad data, you could go about creating a sub warn_once:

但是,如果它实际上是你想要处理的东西但是曾经警告过,比如你想要对数据进行可靠的处理,但是想要警告上游进程你有一些不好的数据,你可以去创建一个子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}++;
    };
}

And call it like this:

并称之为:

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

Then you have decided something.

然后你决定了一些事情。

#1


10  

I thought I would show you how unique warning logic might be created. I don't recommend it though:

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

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

I should say that I do not recommend this as a general practice. Because it's better to have a warning policy. It's either an operation that can take an undefined value, or you don't want to handle an undef value. I try to remove all warnings from my completed code.

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

In the first case, putting no warnings 'uninitialized'; in the for loop is a much easier--and regular thing to do. In the second case, you'd probably want to fail.

在第一种情况下,没有警告“未初始化”;在for循环中是一个更容易 - 而且常规的事情。在第二种情况下,您可能想要失败。

However, if it is something you would actually like to handle but warn once about, say that you wanted robust handling of the data, but wanted to warn upstream processes that you got some bad data, you could go about creating a sub warn_once:

但是,如果它实际上是你想要处理的东西但是曾经警告过,比如你想要对数据进行可靠的处理,但是想要警告上游进程你有一些不好的数据,你可以去创建一个子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}++;
    };
}

And call it like this:

并称之为:

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

Then you have decided something.

然后你决定了一些事情。