STDOUT
a ese fichero y volverlo a poner a su antiguo valor
después de la ejecución. Para ello debemos conservar el antiguo valor de
STDOUT
.
Se puede salvar un manejador de ficheros sin mas que pasárselo
como segundo argumento a open
prefijado de una secuencia
de la forma ">&"
(escritura) o "<&"
(lectura).
El siguiente ejemplo muestra como este mecanismo es utilizado para redirigir temporalmente la salida estandar y restaurarla posteriormente:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ cat -n redirect.pl 1 #!/usr/bin/perl 2 use strict; 3 4 print "Redirecting STDOUT\n"; 5 open (SAVEOUT,">&STDOUT"); 6 open (STDOUT,">test.txt") or die "Can't open test.txt: $!"; 7 print "STDOUT is redirected\n"; 8 system "date"; 9 open (STDOUT,">&SAVEOUT"); 10 print "STDOUT restored\n";Vemos que en la salida estándar se produce la salida:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ ./redirect.pl Redirecting STDOUT STDOUT restoredY en el fichero
test.txt
queda:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ cat test.txt STDOUT is redirected mar abr 18 13:16:45 WEST 2006
La siguiente sesión de comandos con el depurador muestra que la copia mantiene los atributos del original y no es afectado por los cambios a los que se someta al original:
DB<1> open $f, ">&", STDOUT # Salvamos STDOUT en $f DB<2> open STDOUT, "> /tmp/prueba.txt" # Redirigimos STDOUT DB<3> print STDOUT "Hola\n" # /tmp/prueba.txt contiene "Hola\n" DB<4> print $f "Hola\n" # Salida a STDOUT Hola DB<5> !! cat /tmp/prueba.txt # !! Permite ejecutar un comando shell Hola DB<6> close(STDOUT) DB<8> print "Hola" print() on closed filehandle STDOUT at (eval 11) DB<9> print $f "Hola\n" Hola DB<10> print DB::OUT "Hola\n" HolaObsérvese el formato de llamada a open en la línea 1 con tres argumentos.
Nótese que el debugger usa su propio manejador de ficheros de salida DB::OUT
que está
asociado a la terminal (véase perldebug).
Una alternativa a este sistema la provee el método fdopen en IO::Handle que permite reabrir un fichero existente, haciendo una copia en uno nuevo. Una llamada a este método sigue el formato:
$io->fdopen ( $FD, $MODE )La variable
$FD
debe ser un objeto IO::Handle
o un fichero normal o un descriptor numérico.
El modo $MODE
debe casar con el original
de $FD
. El manejador de IO $io
pasa
a tener una copia del manejador $FD
.
En el siguiente ejemplo usamos el método en conjunción con
new_from_fd
(línea 6) el cual crea
un IO::Handle
que es una copia del argumento:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ cat -n redirectIO.pl 1 #!/usr/bin/perl 2 use strict; 3 use IO::File; 4 5 print "Redirecting STDOUT\n"; 6 my $SAVEOUT = IO::File->new_from_fd(\*STDOUT,">"); 7 open(STDOUT, ">test.txt") or die "Can't open test.txt: $!"; 8 print "STDOUT is redirected\n"; 9 system "date"; 10 STDOUT->fdopen($SAVEOUT, ">"); 11 print "STDOUT restored\n";El efecto es el mismo:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ ./redirectIO.pl Redirecting STDOUT STDOUT restoredy el fichero
test.txt
contiene:
lhp@nereida:~/Lperl/src/perl_networking/ch1$ cat test.txt STDOUT is redirected mar abr 18 13:40:14 WEST 2006 lhp@nereida:~/Lperl/src/perl_networking/ch1$
El siguiente programa salva STDIN
usando
open (SAVEIN,"<& STDIN");a continuación se abre de nuevo
STDIN
a un cierto fichero
para leer del mismo durante un cierto periodo (líneas 8-12).
Por último se restaura STDIN
y se pasa a leer desde teclado:
pp2@nereida:~/src/perl/perltesting$ cat -n redirectinput.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 print "Redirecting STDIN to file testin.txt\n"; 5 open (my $SAVEIN,"<& STDIN"); 6 open (STDIN,"<", "testin.txt") or die "Can't open testin.txt: $!"; 7 8 my $x = <STDIN>; 9 chomp($x); 10 11 print "STDIN was redirected. First line of testin.txt: <$x>. Now executing cat -n\n"; 12 system "cat -n "; 13 14 open (STDIN,"<&", $SAVEIN); 15 print "STDIN now restored. Write some input: "; 16 $x = <STDIN>; 17 chomp($x); 18 print "STDIN restored. We read: <$x>\n";Estos son los contenidos del fichero
testin.txt
:
casiano@tonga:~/src/perl/tests$ cat -n testin.txt 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8
Ejecución:
pp2@nereida:~/Lperltesting$ ./redirectinput.pl testin.txt Redirecting STDIN to file testin.txt STDIN was redirected. First line of testin.txt: <1>. Now executing cat -n 1 2 2 3 3 4 4 5 5 6 6 7 7 STDIN now restored. Write some input: my input STDIN restored. We read: <my input> pp2@nereida:~/Lperltesting$
redirectmergestdoutandstderr.pl
redirecciona (de forma independiente del S.O.)
STDOUT
al fichero testmerge.txt
.
Después salva STDOUT
en STDERR
:
pp2@nereida:~/src/perl/perl_networking/ch1$ cat -n redirectmergestdoutandstderr.pl 1 #!/usr/bin/perl 2 use strict; 3 4 # redirect STDOUT 5 open (STDOUT,">testmerge.txt") or die "Can't open test.txt: $!"; 6 7 # merging STDOUT and STDERR 8 open (my $saveerr,">&STDERR"); 9 open (STDERR,">&STDOUT"); 10 11 print "STDOUT is redirected\n"; 12 system "ls -l does.not.exists"; 13 14 open (STDERR,">&", $saveerr); 15 print STDERR "STDERR restored\n";A continuación se ejecutan sentencias y programa(s) que produzcen salida por ambos
STDOUT
y STDERR
como:
print "STDOUT is redirected\n"; system "ls -l does.not.exists";Se mezclan las salidas por
STDERR
y STDOUT
:
pp2@nereida:~/src/perl/perl_networking/ch1$ ./redirectmergestdoutandstderr.pl STDERR restored pp2@nereida:~/src/perl/perl_networking/ch1$ cat -n testmerge.txt 1 STDOUT is redirected 2 ls: no se puede acceder a does.not.exists: No existe el fichero ó directorio pp2@nereida:~/src/perl/perl_networking/ch1$