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$
