Как я могу печатать в переменную вместо файла, в Perl? - PullRequest
8 голосов
/ 08 октября 2009

Как я могу печатать в переменную с помощью Perl?

Я некоторое время работал над программой, которая регистрирует ее итеративный прогресс в очень многословной манере ...

print $loghandle $some_message;

Однако я хотел бы также выборочно распечатать некоторые сообщения в другом файле. Естественно, я мог бы посыпать код ...

print $loghandle $some_message
print $otherloghandle $some_message

Или переписать весь бизнес в функцию. Мля.

Что я хочу сделать, так это сделать немного волшебства, когда я открываю $ loghandle, чтобы, когда я print ', я просто выполнял операцию sprintf ish с переменной (назовите ее $current_iteration), поэтому, когда я подхожу к точке принятия решения, я могу сделать что-то вроде этого ...

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

Я вполне уверен, что где-то видел что-то подобное, но понятия не имею, где это и где искать.

edit: File :: Tee в некоторой степени решает эту проблему на * nix, но я работаю на Windows.

Ответы [ 7 ]

19 голосов
/ 08 октября 2009

Вы можете рассматривать скалярную переменную как дескриптор файла: open ing it:

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

Вы даже можете отобразить стандартный вывод или стандартный вывод на скаляр:

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

Если вы хотите разделить ваш вывод или настроить файл конфигурации для «интересных» вещей с вашей регистрацией, вам лучше использовать Log4Perl , как предлагали другие.

5 голосов
/ 08 октября 2009

Вы имеете в виду нечто вроде IO :: Scalar ? Позволяет записывать в переменную с семантикой дескриптора файла.

4 голосов
/ 08 октября 2009

Если вы хотите сделать выборочную регистрацию, где вы можете контролировать, какие сообщения регистрируются и где они регистрируются, используйте Log :: Log4perl . Это сэкономит вам кучу времени за то, что вы возитесь с tie s и другой черной магией.

2 голосов
/ 08 октября 2009

Perlfaq5 рекомендует Tie :: FileHandle :: Multiplex для печати в несколько файлов.

Источник очень прост и его легко модифицировать с помощью фильтра для каждой ручки.

2 голосов
/ 08 октября 2009

Вы можете использовать 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
1 голос
/ 08 октября 2009

Это потрясающий взлом, и я думаю, что решение mobrule или (esp) решение Синан Log4Perl - это путь, когда у меня есть время.

Но это то, что я использую в качестве дополнения:

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


print_to_var \$logvar, $message;

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

Edit:

Поскольку это вики сообщества, Perl ничего не стоит в качестве аргументов для функций. Это означает, что вы можете просто написать это:

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

А потом скажите:

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

Это не особенно потрясающий взлом, хотя print_to_var намного больше печатает, чем ..

А вот и HELO KITTIE:

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

1 голос
/ 08 октября 2009

Звучит так, как вы хотите 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...