-2

我是 Perl 的新手。我正在编写一些脚本,并想定义我自己的 print 调用myprint(),它将根据一些标志(详细/调试标志)打印传递给它的东西

open(FD, "> /tmp/abc.txt") or die "Cannot create abc.txt file";
print FD "---Production Data---\n";
myprint "Hello - This is only a comment - debug data";

有人可以帮我提供一些示例代码来实现myprint()功能吗?

4

2 回答 2

5

您是否更关心编写自己的日志系统,或者您想知道如何将日志语句放在您可以关闭的程序的适当部分(并且在关闭时几乎不会造成性能损失)?

如果您想要一个易于开始使用的日志系统,同时还提供您可以逐步发现和使用的大量功能,那么Log::Log4perl是一个不错的选择。它有一个简单模式,允许您指定所需的日志记录级别,并仅发出高于所需级别的日志消息。

#!/usr/bin/env perl

use strict; use warnings;

use File::Temp qw(tempfile);
use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init({level => $INFO});

my ($fh, $filename) = tempfile;

print $fh "---Production Data---\n";

WARN 'Wrote something somewhere somehow';

该片段还显示了使用File::Temp打开临时文件的更好方法。

至于覆盖内置打印……除非在非常特殊的情况下,否则摆弄内置插件确实不是一个好主意。perldoc perlsub有一个关于覆盖内置函数的部分。这个问题的公认答案列出了不能被覆盖的 Perl 内置函数print就是其中之一。

但是,那么,一个人真的不需要重写一个内置的来编写一个日志系统。

所以,如果一个已经编写好的日志系统不适合你,你似乎真的在问“我如何编写一个根据标志值有条件地打印内容的函数?”

这是一种方法:

#!/usr/bin/env perl

package My::Logger;
{
    use strict; use warnings;
    use Sub::Exporter -setup => {
        exports => [
            DEBUG => sub {
                return sub {} unless $ENV{MYDEBUG};
                return sub { print 'DEBUG: ' => @_ };
            },
        ]
    };
}

package main;

use strict; use warnings;

# You'd replace this with use My::Logger qw(DEBUG) if you put My::Logger
# in My/Logger.pm somewhere in your @INC
BEGIN {
    My::Logger->import('DEBUG');
}

sub nicefunc {
    print "Hello World!\n";
    DEBUG("Isn't this a nice function?\n");
    return;
}

nicefunc();

示例用法:

$ ./yy.pl
你好世界!
$ MYDEBUG=1 ./yy.pl
你好世界!
调试:这不是一个很好的功能吗?
于 2012-04-07T02:26:28.703 回答
2

我不打算回答这个问题,因为 Sinan 已经有了我推荐的答案,但今晚我也碰巧在为即将到来的Intermediate Perl编写“文件句柄引用”一章。那是几个相关的段落,我将直接复制它们而不使它们适应您的问题:


IO::Null 和 IO::Interactive

有时我们不想将输出发送到任何地方,但我们被迫将其发送到某个地方。在这种情况下,我们可以使用 IO::Null 创建一个文件句柄,它会简单地丢弃我们给它的任何东西。它看起来和行为就像一个文件句柄,但什么也不做:

use IO::Null;

my $null_fh = IO::Null->new;

some_printing_thing( $null_fh, @args );

其他时候,我们在某些情况下想要输出,但在其他情况下不想要。如果我们登录并在终端中运行我们的程序,我们可能希望看到很多输出。但是,如果我们通过cron安排作业,我们可能不会太在意输出,只要它能完成作业。IO::Interactive 模块足够聪明,可以区分:

use IO::Interactive;

print { is_interactive } 'Bamboo car frame';

is_interactive子例程返回一个文件句柄。因为对子例程的调用不是一个简单的标量变量,所以我们用大括号括起来告诉 Perl 它是文件句柄。

现在您了解了“什么都不做”文件句柄,您可以替换一些每个人都倾向于编写的丑陋代码。在某些情况下你想要输出,而在某些情况下你不需要,所以很多人在某些情况下使用后表达式条件来关闭语句:

print STDOUT "Hey, the radio's not working!" if $Debug;

取而代之的是,您可以根据您想要的任何条件分配不同的值,然后 在 every 的末尾$debug_fh去掉丑陋的:if $Debugprint

use IO::Null;

my $debug_fh = $Debug ? *STDOUT : IO::Null->new;

$debug_fh->print( "Hey, the radio's not working!" );

IO::Null 背后的魔力可能会使用间接对象表示法(例如 )发出关于“未打开的文件句柄 GLOB 上的 print()”的警告, print $debug_fh即使它工作得很好。我们没有直接形式的警告。

于 2012-04-07T06:49:56.333 回答