我怎么可以挂钩Perl的打印?

这是一个场景您有大量的遗留脚本,全部使用通用库。所述脚本使用’print’语句进行诊断输出。脚本不允许更改 – 它们范围广泛,有其批准,并且早已离开了富有成果的监督和控制的山谷。

现在已经到了新的需求:现在必须将日志记录添加到库中。这必须自动而透明地进行,没有标准库的用户需要更改其脚本。通用库方法可以简单地添加日志调用;这是很容易的部分。困难的部分在于,这些脚本的诊断输出始终使用’print’语句显示。必须存储此诊断输出,但同样重要的是进行处理。

作为这个处理的一个例子,库应该只记录包含单词“warning”,“error”,“notice”或“attention”的打印行。以下极其简单和有争议的示例代码(tm)将记录一些所述输出

sub CheckPrintOutput
{
    my @output = @_; # args passed to print eventually find their way here.
    foreach my $value (@output) {
         Log->log($value) if $value =~ /warning|error|notice|attention/i;
    }
}

(我想避免这样的问题,应该实际记录什么,打印不应该用于诊断,“perl吸”,或者“这个例子有缺点xy和z”…这是大大简化为了简洁和清晰。)

基本的问题在于捕获和处理传递给打印的数据(或按照这些推理方式,任何perl内置的)。可能吗?有没有办法干净地做?有没有任何记录模块有钩可以让你这样做?还是应该像瘟疫那样避免这样的事情,我应该放弃永远捕捉和处理打印输出

附加:这必须运行跨平台的Windows和* nix。运行脚本的过程必须保持不变,与脚本的输出一样。

附加补充:在codelogic答案的评论中提出了一个有趣的建议:

You can subclass 07000 and create your
own file handle which will do the logging work. – Kamil Kisiel

这可能有两个注意事项:

1)我需要一种将此功能导出到使用公共库的任何人的方法。它必须自动应用于STDOUT,也可能是STDERR。

2)the IO::Handle文件说你不能对它进行子类化,到目前为止我的尝试是无效的。有什么特别需要使子类化IO :: Handle工作吗?标准的’use base’IO :: Handle’然后覆盖新的/打印方法似乎什么都不做。

最终编辑:看起来像IO :: Handle是一个死胡同,但Tie :: Handle可能会这样做。感谢所有的建议;他们都很好我要试穿Tie :: Handle路线。如果造成问题,我会回来的!

附录:注意,在使用这一点后,我发现Tie :: Handle将会工作,如果你不做任何棘手的事情。如果您使用绑定的STDOUT或STDERR的IO :: Handle的任何功能,它基本上是使其工作可靠的难题 – 我找不到一种方法获取IO :: Handle的自动冲洗方法来处理我的绑定处理。如果我在绑定手柄之前启用了自动冲洗,它将会工作。如果这适用于您,Tie :: Handle路线可能是可以接受的。

解决方法

有一些内置的可以覆盖(见 perlsub)。然而,print是其中一种不能以这种方式工作的内置函数。在 perlmonk’s thread年,详细介绍了印刷版的困难。

但是,你可以

>创建一个包
>绑一个手柄
>选择此句柄。

现在有几个人给了基本的框架,但它的工作原理就是这样的:

package IO::Override;
use base qw<Tie::Handle>;
use Symbol qw<geniosym>;

sub TIEHANDLE { return bless geniosym,__PACKAGE__ }

sub PRINT { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    print $OLD_STDOUT join( '','NOTICE: ',@_ );
}

tie *PRINTOUT,'IO::Override';
our $OLD_STDOUT = select( *PRINTOUT );

您可以以相同的方式覆盖printf:

sub PRINTF { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    my $format = shift;
    print $OLD_STDOUT join( '',sprintf( $format,@_ ));
}

请参阅Tie::Handle您可以覆盖STDOUT的行为。

相关文章

忍不住在 PerlChina 邮件列表中盘点了一下 Perl 里的 Web 应用框架(巧的是 PerlBuzz 最近也有一篇相关...
bless有两个参数:对象的引用、类的名称。 类的名称是一个字符串,代表了类的类型信息,这是理解bless的...
gb2312转Utf的方法: use Encode; my $str = "中文"; $str_cnsoftware = encode("utf-8...
  perl 计算硬盘利用率, 以%来查看硬盘资源是否存在IO消耗cpu资源情况; 部份代码参考了iostat源码;...
1 简单变量 Perl 的 Hello World 是怎么写的呢?请看下面的程序: #!/usr/bin/perl print "Hello W...
本文介绍Perl的Perl的简单语法,包括基本输入输出、分支循环控制结构、函数、常用系统调用和文件操作,...