Bienvenido a los foros de Perl en Español, ruben186.
En situaciones sencillas, donde sabemos todos los argumentos que queremos pasarle al programa, solo necesitamos enviar los argumentos y responder a las preguntas y seleccionar las opciones, tal como lo haríamos si fuéramos nosotros los que manejáramos el programa.
Por ejemplo, tenemos un programa que nos pide los nombres de los archivos de entrada y salida, y además hace una pregunta a la que siempre responderemos con un 'N':
Using text Syntax Highlighting
enter file name (you must specify the file name and press Enter)
do you want to specify another file name (Y/N) (you must enter N in most cases and press Enter)
enter name for output file (you must specify a name for the output file, eg ttt and press Enter)
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Vamos a hacer un programa Perl que imite ese comportamiento:
Using perl Syntax Highlighting
#! perl -slw
use strict;
print "enter file name (you must specify the file name and press Enter)";
chomp( my $infile = <STDIN> );
print "do you want to specify another file name (Y/N) (you must enter N in most cases and press Enter)";
chomp( my $another = <STDIN> );
print "enter name for output file (you must specify a name for the output file, eg ttt and press Enter)";
chomp( my $outfile = <STDIN> );
print "reading $infile; writing $outfile";
exit 99;
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Bueno, ahora el trabajo es hacer un programa que sea capaz de manejar el anterior. Puede hacerse así:
Using perl Syntax Highlighting
#! perl -slw
use strict;
my $progname = "java jar $ruta_fichero_jar $parametro1 $parametro2";
my $pid = open CMD, '|-', $progname or die $!;
print CMD 'myInfile';
print CMD 'N';
print CMD 'myOutfile';
close CMD;
waitpid $pid, 0;
print "$progname ended: status: ", $? >>8;
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Entonces:
- en lugar de usar las comillas invertidas (el operador qx()) que solo ejecuta un programa y nos devuelve el resultado, usamos un open(), que abre una tubería (de shell), encauzando la salida de nuestro programa hacia el anterior programa ($progname)
- como sabemos las tres cosas que el programa nos pide, se las enviamos en sendos print (atención a la opción -l de la primera línea del programa: hace que cada print termine de forma automática con un "\n")
- cerramos la tubería, y esperamos que $progname termine
- sacamos el resultado a pantalla (¡Ojo! no es la salida del programa, sino el resultado de la ejecución)
Pero esto funciona si solo queremos ejecutar el $progname, mandándole por la entrada estándar los parámetros, y no esperamos ninguna salida (quizás porque la salida la grabará a disco).
Más información en tu propio ordenador en
perldoc perlopentut,
y en la Web.
Si, como sospecho, también quisieras capturar la salida de $progname, lo más cómodo entonces es usar
IPC::Open2:
Using perl Syntax Highlighting
use IPC::Open2;
local(*CHLD_OUT, *CHLD_IN); # Crea gestores de archivo locales, si es necesario
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'java jar $ruta_fichero_jar $parametro1 $parametro2');
print CHLD_IN "archivo1.txt\n"; # le mandamos un argumento
print CHLD_IN "N\n"; # respondemos a una pregunta
print CHLD_IN "archivo2.txt\n"; # le mandamos otro argumento
my $respuesta_del_programa = <CHLD_OUT>; # leemos su respuesta (una línea)
my @respuesta_del_programa = <CHLD_OUT>; # leemos el resto de la respuesta
close CHLD_IN;
close CHLD_OUT;
waitpid($pid, 0); # vigilamos que se muera bien muerto... podría convertirse en zombie
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
El módulo IPC::Open2 exporta la función open2(), que permite entubar nuestra salida estándar hacia el programa externo, y luego poder leer lo que nos manda.
Más información sobre esto.
Si necesitas un control más estricto sobre el diálogo entre los dos programas, entonces lo recomendado es usar
Expect.