• Publicidad

Pasar variables como argumento a función qx()

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Pasar variables como argumento a función qx()

Notapor kordlhesh » 2018-04-26 13:58 @623

Hola.

Tengo el siguiente código de Perl, en el que lo que quiero es poder cambiar el nombre de un archivo para poder sacar los resultados de muchos archivos con diferentes parámetros.

El caso es que no consigo que la función qx() entienda bien la variable $lista_out.

He probado a poner una dirección fija como string, y el script funciona sin problemas, pero en el momento en que añado el bucle, y $lista_out pasa a contener una variable, qx() no lo entiende. Entiendo que sprintf() me devuelve la variable formateada como un string, por lo que no debería haber problema, ¿no?

Llevo unos días mirando por todos lados pero... no encuentro por ningún lado la solución.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2. use strict;
  3. use warnings;
  4.  
  5. for (my $i=2; $i <= 10; $i++) {
  6.         my $lista_out = sprintf("listas/lista_resultados_%.1f\.list", $i);
  7.         printf $lista_out; # visualizar el nombre del fichero de resultados
  8.         printf "\n\n";
  9.        
  10.         my $lista_ref = "listas/lista_referencia.list";
  11.  
  12.         my $info_out = qx(perl tools/script1.pl -R $lista_ref -S $lista_out) or die "Error en qx()";
  13.                
  14.         print $info_out;       
  15. }
  16.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
kordlhesh
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2018-04-26 13:49 @617

Publicidad

Re: Pasar variables como argumento a función qx()

Notapor explorer » 2018-04-26 16:00 @708

Bienvenido a los foros de Perl en Español, kordlhesh.

Pues sí que es extraña la situación...

En efecto, la variable dentro de la cadena de caracteres no debería dar problemas. Y de hecho, yo no veo problemas en ninguna parte del código.

Ahora bien... cuando ejecutas un qx() lo que estás haciendo es llamar al shell para que ejecute otro programa con una serie de argumentos... y es en ese momento cuando los argumentos pueden quedar afectados por la interpretación del shell (caso de tener comodines, espacios en blanco, cosas así. Pero veo que no es tu caso.

¿Estamos seguros que el problema es $lista_out? ¿Lo recibe bien script1.pl? ¿Qué errores da?

Algo que puedes hacer sin problemas es editar script1.pl, ir a las primeras líneas del código y poner algo como esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. print "[" . join("][" => @ARGV) . "]";
  3. exit;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Es decir, que queremos que formatee los argumentos que recibe poniéndolos entre corchetes, los mande a la salida estándar, y que el programa termine. La salida será capturada por el qx() de tu programa, y lo sacarás en pantalla. Así verás qué es lo que realmente está recibiendo script1.pl.

Por ejemplo, yo he hecho una versión moderna de tu código y le he añadido la impresión del resultado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.10;
  3. use strict;
  4. use warnings;
  5.  
  6. my $lista_ref = "listas/lista_referencia.list";
  7.  
  8. for my $i (2 .. 10) {
  9.     my $lista_out = sprintf("listas/lista_resultados_%.1f.list", $i);
  10.     #say "OUT: [$lista_out]";
  11.  
  12.     my $info_out = qx(perl tools/script1.pl -R $lista_ref -S $lista_out) or die "Error en qx()";
  13.     say "RES: [$info_out]";      
  14. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y este es el script que recibe la llamada:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. print "[" . join("][" => @ARGV) . "]";
  3. exit;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Esta es la salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_2.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_3.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_4.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_5.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_6.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_7.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_8.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_9.0.list]]
RES: [[-R][listas/lista_referencia.list][-S][listas/lista_resultados_10.0.list]]
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Observa en las líneas RESultado cómo los corchetes van separando los argumentos. El contenido de $lista_out está correcto, así que mi shell no ha hecho nada raro con él.

Entonces, si tu programa emite los argumentos de forma correcta, y script1.pl los recibe también de forma correcta, quiere decir que es en el propio script1.pl donde está el fallo a la hora de trabajar con ellos.

Tendrás que poner controles dentro de script1.pl.

Veo que son archivos. ¿script1.pl sabe llegar a ellos?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Pasar variables como argumento a función qx()

Notapor kordlhesh » 2018-04-26 16:13 @717

Hola.

Lo primero, muchas gracias por responder tan rápido :D

Al guardar lo que devuelve la función qx() en una variable, y luego imprimirla por la ventana de comandos, por defecto ya hace eso que comentas, y me devuelve una línea de este tipo:

command line (run on 2018 Apr 26 at 20:46:47): tools/script1.pl -R listas/lista_referencia.list -S listas/results_1.0.list

Por lo que veo que recibe bien la variable. De hecho probé a cambiarlo, y si usaba printf() por ejemplo en lugar de sprintf(), cambiaba esa dirección por un "1" (entiendo que la salida de printf() tendrá una comprobación de si se ha realizado bien, y de ahí el 1").

De la misma forma también he probado a cambiar de lugar los archivos, al mismo directorio que el script, y sucede lo mismo. De hecho lista_referencia.list está en la misma carpeta que las listas de resultados, así que probé a guardar la dirección de lista_referencia en otra variable, para ver si pudiera ser el problema que comentas de que no encuentra el archivo, pero solo me da problemas cuando lo que recibe como argumento es la variable de salida del sprintf().

Error como tal no me da ninguno (a nivel de sintaxis o de warnings), pero el script debería mostrar una serie de resultados que no muestra y que, si cambio la variable por la dirección del archivo escrita así "entrecomillada", sí lo entiende y los muestra.

Al principio pensé que igual me faltaba llamar a una biblioteca o algo y que no estaba usando bien el sprintf() el script, pero al ver que en la línea de comandos le ha llegado sin problema esa información... no acabo de entender lo que pasa. Nunca había programado nada en Perl y desconozco qué bibliotecas hacen falta para cada cosa (recuerdo que en C había una <string.h> para la mayoría de cosas relacionadas con cadenas de caracteres, pero no sé cómo aplica eso en Perl).
kordlhesh
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2018-04-26 13:49 @617

Re: Pasar variables como argumento a función qx()

Notapor explorer » 2018-04-27 13:55 @621

kordlhesh escribiste:De hecho probé a cambiarlo, y si usaba printf() por ejemplo en lugar de sprintf(), cambiaba esa dirección por un "1" (entiendo que la salida de printf() tendrá una comprobación de si se ha realizado bien, y de ahí el 1").
En efecto, el "1" es un valor booleano que printf() devuelve indicando que ha conseguido el propósito de sacar la cadena de texto por la salida estándar (o por la salida que el indicador de archivo señale).

kordlhesh escribiste:Error como tal no me da ninguno (a nivel de sintaxis o de warnings), pero el script debería mostrar una serie de resultados que no muestra y que, si cambio la variable por la dirección del fichero escrita así "entrecomillada", sí lo entiende y los muestra.
¿Tienes advertencias (warn/die) en los procesos de open() del archivo recibido como argumento? Usa la línea

use autodie;

al principio del script1.pl, para que cualquier operación de archivos que falle provoque una parada y se emita un mensaje de error. Si no tienes instalado autodie, hazlo. Te ahorrará muchos dolores de cabeza para descubrir estos errores y te ahorrará escribir mucho código.

kordlhesh escribiste:Al principio pensé que igual me faltaba llamar a una biblioteca o algo y que no estaba usando bien el sprintf() el script, pero al ver que en la línea de comandos le ha llegado sin problema esa información... no acabo de entender lo que pasa. Nunca había programado nada en Perl y desconozco qué bibliotecas hacen falta para cada cosa (recuerdo que en C había una <string.h> para la mayoría de cosas relacionadas con cadenas de caracteres, pero no sé cómo aplica eso en Perl).

En Perl, con la funcionalidad que trae por defecto, ya es suficiente para hacer muchas de las operaciones básicas. No es necesario importar nada, salvo operaciones muy, muy especiales.

Sin ver el código es complicado decir dónde puede estar el error.

¿Puedes crear una copia de los dos programas, y quitarles todas las líneas que puedas, hasta conseguir llegar a la mínima expresión del error? Es decir, intenta reproducir el error con el menor número posible de líneas, y publicar aquí el código de los dos programas. Fíjate que es lo mismo que he intentado hacer, y funciona (no has dicho si lo has probado y si te funciona). Bueno, pues es cuestión luego de añadirle líneas hasta que falle. O quitarle/comentarle líneas al programa original mientras falle.

Y describirnos un poco el entorno: en qué carpetas están los programas, en qué carpetas están los archivos de los que quieres acceder, a los que quieres escribir...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Pasar variables como argumento a función qx()

Notapor kordlhesh » 2018-04-28 07:02 @335

Hola.

Ya solucioné el problema y... era un fallo terrible de novato. Un despiste.

En efecto, comprobé si mi script funcionaba con las líneas para el otro script que comentabas, y devolvía los nombres de los ficheros sin problema.

autodie no encontré cómo instalarlo, pero miré que estuvieran todos los archivos, porque aunque comprobé que el script era capaz de buscarlos en el directorio en el que los tengo, al ser resultados de un algoritmo con variaciones en varios parámetros no había comprobado si todos los resultados estaban generados, y estaba buscando archivos que aún no existían.

He probado a cambiar el nombre del sprintf() por el de unos archivos que sí sé que he generado al completo, y lo procesa sin problemas.

Hay veces que uno se da de cabeza contra el aparente error, cuando al final es la cosa más tonta y obvia... :mrgreen: :mrgreen:

Muchas gracias por la ayuda y los consejos prestados. Un saludo.
kordlhesh
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2018-04-26 13:49 @617


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 19 invitados