【问题标题】:Is there a way to be notified when 'print' is called on $fh?有没有办法在 $fh 上调用 'print' 时得到通知?
【发布时间】:2015-09-30 15:52:29
【问题描述】:

当我这样做时:

print $fh 'text';

我需要一些 &sub 来调用。

有办法吗?

【问题讨论】:

  • sub myprint { mysub(); print @_ } 也许? (您不能使用名为sub 的子名称,它是保留名称)
  • 用绑定的文件句柄替换文件句柄
  • 虽然您可以覆盖很多内置插件,但对于 print,您不能这样做。见perldoc.perl.org/CORE.html

标签: perl filehandle


【解决方案1】:

您可以tie a filehandle 并自定义print对该文件句柄或对该文件句柄的任何其他操作的行为。

sub PrintNotifier::TIEHANDLE {
    my ($pkg, $orignalHandle) = @_;
    bless { glob => $orignalHandle }, $pkg;
}
sub PrintNotifier::PRINT {
    my ($self,@msg) = @_;
    ... do whatever you want with @msg here ...
    return print {$self->{glob}} @msg;
}
sub PrintNotifier::CLOSE { return close $_[0]->{glob} }

open my $fh, '>', 'some-file';
tie *$fh, 'PrintNotifier', $fh;
print $fh "something";           # calls  PrintNotifier::PRINT

【讨论】:

    【解决方案2】:

    你可以tie 手柄,正如暴民建议的那样。或者,如果您可以更改代码并且您的 Perl 足够新,则可以替换

    print $fh 'text';
    

    $fh->print('text');
    

    你可能会考虑更简洁的语法;那么你可以子类 IO::File:

    package MyFH {
        use parent qw/ IO::File /;
        use mro; # Get next::method
    
        sub print {
            my ($self, @args) = @_;
    
            warn 'Printing ', @args;
            $self->next::method(@args);
        }
    }
    
    my $fh = MyFH->new();
    $fh->open('file', '>') or die $!;
    

    然而,这并没有捕捉老式的

    print $fh 'text';
    

    风格。

    根据您的喜好,您可能会发现新的样式更清洁,因为如果您的文件句柄是它允许的表达式

    $obj->method()->print('text');
    

    而不是

    print {$obj->method()} 'text';
    

    它对 Perl 5.14 及更高版本透明地工作,并且可以通过添加使旧的 Perls 工作回到(至少)5.8

    use IO::Handle;
    

    到您要使用它的文件的顶部(只是为了安全起见)。

    【讨论】:

      【解决方案3】:

      perl 中没有记录,但在usage 中很有用

      如果您想在您的班级中的对象上处理打印,您可以将其绑定

      tie *$self, $self;
      print $self 'text';
      $self->print( 'text' );
      

      【讨论】: