2009-10-07 10 views
7

¿Cómo puedo imprimir una variable con Perl?¿Cómo puedo imprimir en una variable en lugar de un archivo, en Perl?

He estado trabajando en un programa durante un tiempo que registra su iterativo el progreso de una manera muy prolijo ...

print $loghandle $some_message; 

Sin embargo, me gustaría también imprimir selectivamente algunas de las mensajes a un archivo diferente. Naturalmente, podría rociar el código con ...

print $loghandle $some_message 
print $otherloghandle $some_message 

O reescribir todo el asunto en una función. Paja.

Lo que quiero hacer es hacer un poco de magia cuando abro el $ loghandle de manera que cuando estoy print 'ing, en realidad estoy simplemente haciendo una operación sprintf ish contra una variable (llámese $current_iteration), de manera que cuando llegue a un punto de decisión que pueda hacer algo como esto ...

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

estoy bastante seguro de que he visto algo como esto en alguna parte, pero no tengo ni idea de dónde está o dónde buscar .

editar: File :: Tee resuelve este problema hasta cierto punto en * nix, pero corro en 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

Posiblemente. No estoy tratando de ver las transmisiones realmente (aunque eso no importa); es más establecer una variable para actuar como una secuencia de destino. Estoy siendo flojo y no quiero reescribir 50 mensajes de registro, mira. :-) –

+2

@Paul Nathan I vinculado a la respuesta de Brian Foy. Use Log4perl. Exprese su '$ condición' como un nivel de registro, defina las acciones. No estoy agregando esto como una respuesta, ya que no tengo tiempo para comprobar cómo funciona, pero recomendaría Log4perl a fondo en función de la experiencia pasada. –

Respuesta

18

se puede tratar a una variable escalar como un gestor de archivo por open ing que:

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

incluso se puede asignar la salida estándar o stderr a una escalar:

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

Si usted w Para dividir su salida o configurar un archivo de configuración para hacer cosas "interesantes" con su registro, es mejor que lo haga con Log4Perl, como han sugerido otros.

2

Puede usar File::Tee para dividir un manejador de archivos en múltiples flujos de salida.

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 en Windows (File :: Tee no). agregando eso a la pregunta. –

1

Parece que usted quiere tie su identificador de archivo.

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

Creo que sí, pero hoy soy tonto y no veo cómo funciona realmente el vínculo aquí. –

5

¿Te refieres a algo así como IO::Scalar? Le permite escribir en una variable con semántica de manejo de archivos.

+3

No necesita IO :: Scalar explícitamente. open() por sí solo funciona bien. –

1

Esto es tremendo truco, y creo que la solución de mobrule o (especialmente) la solución de Sinan de Log4Perl son el camino a seguir cuando tengo tiempo.

Pero, esto es lo que estoy usando, como una cosa completado:

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


print_to_var \$logvar, $message; 

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

Editar:

Dado que esta es la comunidad wiki, vale la pena nada de lo que Perl alias argumentos de funciones. Eso significa que usted puede escribir esto:

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

y luego decir:

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

Esto no es particularmente un tremendo corte, aunque es print_to_var lleva mucho más trabajo que es ..

Y aquí es el KITTIE HELO:

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

+0

¡Me divierto! Y no estaba seguro acerca de los args de aliasing/referencing a las funciones. ¡Gracias! –

4

Si desea hacer un registro selectivo donde puede controlar qué mensajes se registran y dónde se registran, use Log::Log4perl. Eso le ahorrará un montón de tiempo al jugar con tie sy otras magias negras.

Cuestiones relacionadas