2010-12-11 9 views
8

Quiero redirigir STDERR y STDOUT a una variable. Hice esto.Cómo redirigir STDOUT y STDERR a una variable

close(STDOUT); 
close(STDERR); 

my $out; 
open(STDOUT, ">>", \$out); 
open(STDERR, ">>", \$out); 

for(1..10) 
{ 
    print "print\n"; # this is ok. 
    warn "warn\n"; # same 
    system("make"); # this is lost. neither in screen nor in variable. 
} 

El problema con system. Quiero que la salida de esta llamada sea capturada también.

Respuesta

3

¿Está buscando capturar la salida en una variable? En caso afirmativo, debe utilizar los puntos suspensivos o qx{} con la redirección adecuada. Por ejemplo, podría utilizar:

#/usr/bin/env perl 
use strict; 
use warnings; 

# Ensure we have a way to write messages 
open my $fh, '>', "output" or die; 

close(STDOUT); 
close(STDERR); 

my $out; 
open(STDOUT, ">>", \$out) or do { print $fh, "failed to open STDOUT ($!)\n"; die }; 
open(STDERR, ">>", \$out) or do { print $fh, "failed to open STDERR ($!)\n"; die }; 

foreach my $i (1..10) 
{ 
    print "print $i\n"; 
    warn "warn $i\n"; 
    my $extra = qx{make pth$i 2>&1}; 
    print $fh "<<$i>><<$out>><<$extra>>\n"; 
} 

(me sucede que tiene programas PTH1, PTH2 y pth3 en el directorio - que se hicieron bien; pth4 y por encima de errores de escritura en stderr; la reorientación era necesario.)

Siempre debe verificar el éxito de operaciones tales como open().

¿Por qué es esto necesario? Debido a que escribir en una variable requiere la cooperación del proceso de escritura, y make no sabe cómo cooperar.

2

La razón de que esto está sucediendo es que el stdout y stderr "filehandles" son no equivalente a stderr y stdout tiradores suministro proporcionado por la cáscara para el binario de Perl. Para lograr lo que desea, debe usar open en lugar de system

+0

$ out. = Qx {make}; funciona pero no creo que sea una buena manera. – Deck

+2

@Israfil: es * la * forma de hacerlo. –

1

¿Por qué no use IPC::Open3?

+0

Porque no funciona bien en Win32. – dolmen

0

Hay varias maneras de redirect and restore STDOUT. Algunos de ellos también trabajan con STDERR. Aquí están mis dos favoritos:

Uso select:

my $out; 
open my $fh, ">>", \$out; 
select $fh; 
print "written to the variable\n"; 
select STDOUT; 
print "written to original STDOUT\n"; 

Uso local:

my $out 
do { 
    local *STDOUT; 
    open STDOUT, ">>", \$out; 
    print "written to the variable\n"; 
}; 
print "written to original STDOUT\n"; 

disfrutar.

Cuestiones relacionadas