2009-10-07 13 views
7

Come posso stampare su una variabile con Perl?Come posso stampare su una variabile invece di un file, in Perl?

ho lavorato su un programma per un po ', che registra la sua iterativa il progresso in un modo altamente dettagliato ...

print $loghandle $some_message; 

Tuttavia, mi piacerebbe anche stampare in modo selettivo alcuni dei messaggi in un altro file. Naturalmente, potrei cospargere il codice con ...

print $loghandle $some_message 
print $otherloghandle $some_message 

Oppure riscrivere l'intera attività in una funzione. Blah.

Quello che voglio fare è di fare un po 'di magia quando apro il $ loghandle in modo che quando sono print 'ing, sto solo facendo un'operazione di sprintf ish contro una variabile (lo chiamano $current_iteration), in modo che quando arrivo fino a un punto di decisione che posso fare qualcosa di simile ...

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

sono abbastanza sicuro che ho visto qualcosa di simile da qualche parte, ma non ho idea di dove sia o dove andare a cercare .

modifica: File :: Tee risolve questo problema in una certa misura su * nix, ma corro su Windows.

+2

Deja vu? http://stackoverflow.com/questions/1532544/how-can-i-send-stdout-and-stderr-to-a-log-file-and-to-the-screen-in-win32-perl/1532691# 1532691 –

+0

Forse. Non sto provando davvero a riprodurre i flussi reali (anche se non importa); è più l'impostazione di una variabile che funge da flusso di destinazione. Sono pigro e non voglio riscrivere 50 messaggi di registrazione dispari, vedi. :-) –

+2

@Paul Nathan mi sono collegato alla risposta di brian d foy. Usa Log4perl. Esprimi la tua '$ condizione' come livello di registrazione, definisci le azioni. Non sto aggiungendo questo come una risposta in quanto non ho il tempo di verificare come funziona, ma consiglio vivamente Log4perl sulla base dell'esperienza passata. –

risposta

18

si può trattare una variabile scalare come filehandle dal open ing esso:

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

È anche possibile mappare stdout o stderr a un scalare:

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

Se si w per dividere il tuo output o impostare un file di configurazione per fare cose "interessanti" con il tuo logging, stai meglio con Log4Perl come altri hanno suggerito.

2

È possibile utilizzare File::Tee per dividere un filehandle in più flussi di output.

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 
+0

Corro su Windows (File :: Tee no). aggiungendo questo alla domanda. –

1

Suono come si desidera tie il filehandle.

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; 
    } 
} 
+0

Penso di sì, ma oggi sono stupido e non vedo come funziona davvero il legame. –

5

Intendi qualcosa come IO::Scalar? Consente di scrivere su una variabile con semantica di filehandle.

+3

Non è necessario IO :: Scalar esplicitamente. open() di per sé funziona bene. –

1

Questo è un enorme mod, e penso che la soluzione di mobrule o (specialmente) la soluzione di Sinan di Log4Perl siano la strada da percorrere quando ho tempo.

Ma, questo è quello che sto usando, come una cosa di completamento:

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


print_to_var \$logvar, $message; 

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

Edit:

Dal momento che questa è la comunità wiki, vale la pena nulla che Perl alias argomenti alle funzioni. Ciò significa che si può semplicemente scrivere questo:

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

e poi dire:

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

Questo non è un particolarmente tremenda hack, anche se print_to_var è molto più di battitura di . è.

E qui è il KITTIE HELO:

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

+0

Sono divertito! E non ero sicuro delle funzioni di aliasing/referencing. Grazie! –

4

Se si desidera eseguire la registrazione selettiva in cui è possibile controllare quali messaggi vengono registrati e dove sono registrati, utilizzare Log::Log4perl. Ciò ti farà risparmiare un sacco di tempo oltre a scherzare con tie s e altre magie nere.

Problemi correlati