2010-12-11 15 views
8

Desidero reindirizzare STDERR e STDOUT a una variabile. L'ho fatto.Come reindirizzare STDOUT e STDERR a una variabile

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. 
} 

Il problema con system. Voglio che anche l'output di questa chiamata venga catturato.

risposta

3

Stai cercando di acquisire l'output in una variabile? In tal caso, utilizzare i backtick o qx{} con un reindirizzamento appropriato. Ad esempio, è possibile utilizzare:

#/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"; 
} 

(mi capita di avere programmi pth1, PTH2 e pth3 nella directory - sono state fatte su OK; pth4 e soprattutto errori di scrittura su stderr, il reindirizzamento è stato necessario.)

Si dovrebbe sempre verificare il successo di operazioni come open().

Perché è necessario? Perché scrivere su una variabile richiede la cooperazione del processo che fa la scrittura - e make non sa come collaborare.

2

La ragione questo accade è che lo STDOUT e STDERR "filehandles" sono non equivalente stderr e stdout apposite maniglie fornite dalla shell al binario perl. Per ottenere ciò che desideri, devi utilizzare open anziché system

+0

$ out. = Qx {make}; funziona ma non penso che sia un buon modo. – Deck

+2

@Israfil: è * il * modo di farlo. –

1

Perché non use IPC::Open3?

+0

Perché non funziona bene su Win32. – dolmen

0

Ci sono diversi modi per redirect and restore STDOUT. Alcuni di essi funzionano anche con STDERR. Qui ci sono i miei due preferiti:

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"; 

godere.

Problemi correlati