简体   繁体   English

如何在Perl中打印变量而不是文件?

[英]How can I print to a variable instead of a file, in Perl?

How can I print to a variable with Perl? 如何使用Perl打印到变量?

I've been working on a program for a while which logs its iterative progress in a highly verbose fashion... 我一直在研究一个程序,它以高度冗长的方式记录它的迭代进度......

print $loghandle $some_message;

However, I'd like to also selectively print some of the messages to a different file. 但是,我还想有选择地将一些消息打印到不同的文件中。 Naturally, I could sprinkle the code with... 当然,我可以将代码撒上......

print $loghandle $some_message
print $otherloghandle $some_message

Or rewrite the whole business into a function. 或者将整个业务重写为一个功能。 Blah. 等等。

What I want to do is do some magic when I open the $loghandle so that when I'm print 'ing, I'm actually just doing a sprintf ish operation against a variable(call it $current_iteration ), so that when I get down to a decision point I can do something like this... 我想要做的就是在打开$ loghandle时做一些魔术,这样当我print时,我实际上只是对一个变量做一个sprintf ish操作(称之为$current_iteration ),所以当我得到到决策点我可以做这样的事......

print $real_log_file $current_iteration;
print $other_real_log_file $current_iteration if($condition);

I'm fairly sure I've seen something like this somewhere, but I have no idea where it is or where to look. 我很确定我在某个地方见过这样的东西,但我不知道它在哪里或在哪里看。

edit: File::Tee solves this problem to some extent on *nix, but I run on Windows. 编辑:File :: Tee在某种程度上在* nix上解决了这个问题,但我在Windows上运行。

You can treat a scalar variable as a filehandle by open ing it: 您可以通过open它来将标量变量视为文件句柄:

open my $fh, '>', \$variable or die "Can't open variable: $!";
print $fh "Treat this filehandle like any other\n";

You can even map stdout or stderr to a scalar: 您甚至可以将stdout或stderr映射到标量:

close STDOUT;
open STDOUT, '>', \$variable or die "Can't open STDOUT: $!";

If you want to split your output or set up a config file to do "interesting" things with your logging, you are better off with Log4Perl as others have suggested. 如果您想分割输出或设置配置文件以便在日志记录中执行“有趣”的操作,那么最好使用其他人建议的Log4Perl

Do you mean something like IO::Scalar ? 你的意思是IO :: Scalar吗? Lets you write to a variable with filehandle semantics. 允许您使用文件句柄语义写入变量。

If you want to do selective logging where you can control which messages are logged and where they are logged, use Log::Log4perl . 如果要进行选择性日志记录,可以控制记录哪些消息以及记录哪些消息,请使用Log :: Log4perl That will save you a bunch of time over messing with tie s and other black magic. 这将节省你一堆时间搞乱tie和其他黑魔法。

You can use File::Tee to split a filehandle into multiple output streams. 您可以使用File :: Tee将文件句柄拆分为多个输出流。

use File::Tee;
open my $fh, '>', 'logfile.txt' or die $!;
tee( $fh, '>', 'otherlogfile.txt' ) if $condition;

print $fh $current_iteration;   # will also go to otherlogfile.txt 
                                # if $condition was true

Perlfaq5 recommends Tie::FileHandle::Multiplex for printing to multiple files. Perlfaq5推荐使用Tie :: FileHandle :: Multiplex打印到多个文件。

The source is very simple and it should be easy to modify with a per-handle filter. 源代码非常简单,应该很容易使用每个句柄过滤器进行修改。

Sound like you want to tie your filehandle. 声音就像你想要tie档文件一样。

my $x;

# printing to $fh will update the variable $x
# when you close $fh, it will print $x to a filehandle depending
# on code in the function  Print_to_variable::CLOSE 

tie $fh, "Print_to_variable", \$x, $output_fh1, $output_fh2;
print $fh "stuff";
print $fh "more stuff";
close $fh;

sub Print_to_variable::TIEHANDLE {
    my ($class, $ref, $fh1, $fh2) = @_;
    my $self = {};
    $self->{ref} = $ref;
    $self->{output_fh1} = $fh1;
    $self->{output_fh2} = $fh2;
    bless $self, "Print_to_variable";
    $self;
}
sub Print_to_variable::PRINT {
    my ($self,@list);
    ${$self->{ref}} .= join "", @list;
}
sub Print_to_variable::CLOSE {
    my $self = shift;
    my $text = ${$self->{ref}};
    if ( &myCondition1($text) ) {    # ... how you decide where to print 
        print {$self->{output_fh1}} $text;
    } else {
        print {$self->{output_fh1}} $text;
    }
}

This is a tremendous hack, and I think mobrule's solution or(esp) Sinan's solution of Log4Perl are the way to go when I have time. 这是一个巨大的黑客,我认为mobrule的解决方案或(特别是)Sinan的Log4Perl解决方案是我有时间的方式。

But, this is what I'm using, as a completion thing: 但是,这就是我正在使用的,作为完成的事情:

sub print_to_var($$) {
   my($rx_var, $scalar) = @_;
   $$rx_var .= $scalar;
}


print_to_var \$logvar, $message;

#...later on...
print $somefile $logvar;

Edit: 编辑:

Since this is community wiki, it's worth nothing that Perl aliases arguments to functions. 由于这是社区维基,因此Perl将函数的参数别名化是没有价值的。 That means you can just write this: 这意味着你可以写下这个:

sub print_to_var($$) {
   $_[0] .= $_[1];
}

And then say: 然后说:

my $foo = "OH HAI. ";
print_to_var $foo, "I ARE HELO KITTIE.";
say $foo; # OH HAI.  I ARE HELO KITTIE.

This is not a particularly tremendous hack, although print_to_var is a lot more typing than . 这不是一个特别大的黑客,虽然print_to_var比打字更多. is. 是。

And here is the HELO KITTIE: 这是HELO KITTIE:

helo kittie http://blogs.philadelphiaweekly.com/style/files/2008/11/hello-kitty-color.gif helo kittie http://blogs.philadelphiaweekly.com/style/files/2008/11/hello-kitty-color.gif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM