¿Por qué mi script Perl se queja sobre el "símbolo global" $ random_name "requiere un nombre de paquete explícito"?

StackOverflow https://stackoverflow.com/questions/1616666

  •  06-07-2019
  •  | 
  •  

Pregunta

Estoy aprendiendo Perl y, al mismo tiempo, estoy creando un programa para los eventos de mi familia, pero cuando intento usar una matriz con un proceso de aleatorización, obtengo algunos errores, como puede ver:

[ubuntu@eeepc:~/Desktop/mail] ./get.pl -h pop.vix.terra.com.br -u nathanpc -p  (:D)
Global symbol "$random_name" requires explicit package name at ./get.pl line 17.
Execution of ./get.pl aborted due to compilation errors.
[ubuntu@eeepc:~/Desktop/mail]

Y mi código es así:

#!/usr/bin/perl

# import packages
use Net::POP3;
use Getopt::Long;
use Mail::Message;
use List::Util qw(shuffle);
use strict;
use warnings;

# Variable declaration
my $host;
my $user;
my $pass;
my $email_file;
my $msg;
my @array = shuffle(<$random_name>);

# read command line options
# display usage message in case of error
GetOptions ('h|host=s' => \$host,
            'u|user=s' => \$user,
            'p|pass=s' => \$pass) or die("Input error. Try calling me with: -h <host> -u <username> -p <password>");

# file operations
open($email_file, ">>", "Mail.txt");
open my $random_name, "<", "out.txt";

# initiate connection
# default timeout = 120 sec
my $conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");

# login
my $numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");

# get message numbers
# iterate over list and print first 20 lines of each
if ($numMsg > 0) {
    my $msgList = $conn->list();
    foreach $msg (keys(%$msgList)) {
        my $rawdata = $conn->get($msg);
        my $msg_obj = Mail::Message->read($rawdata);
        my $body = $msg_obj->body;
        print $email_file $body;
        print $email_file "\n====================================================\n";
        print shift @array;
    }
} else {
    print "Mailbox is empty.\n";   
}

# close connection
$conn->quit();
close($email_file);
close($random_name);
¿Fue útil?

Solución

Las respuestas de Greg Hewgill y ~ unutbu son correctas. Solo quería agregar que es mejor no declarar previamente las variables, que pueden haber ayudado un poco a comprender lo que estaba mal.

Aquí está su código idéntico con algunos cambios leves:

#!/usr/bin/perl

# import packages
use Net::POP3;
use Getopt::Long;
use Mail::Message;
use List::Util qw(shuffle);
use strict;
use warnings;

# read command line options
# display usage message in case of error
my ($host, $user, $pass);
GetOptions ('h|host=s' => \$host,
            'u|user=s' => \$user,
            'p|pass=s' => \$pass) or die("Input error. Try calling me with: -h <host> -u <username> -p <password>");

# file operations
open (my $email_file, ">>", "Mail.txt") or die ("Error opening Mail.txt for write: $!");
open (my $random_name, "<", "out.txt") or die ("Error opening out.txt for read: $!");
my @array = shuffle(<$random_name>);
close($random_name);

# initiate connection
# default timeout = 120 sec
my $conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");

# login
my $numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");

# get message numbers
# iterate over list and print first 20 lines of each
if ($numMsg > 0) {
    my $msgList = $conn->list();
    foreach my $msg (keys(%$msgList)) {
        my $rawdata = $conn->get($msg);
        my $msg_obj = Mail::Message->read($rawdata);
        my $body = $msg_obj->body;
        print $email_file $body;
        print $email_file "\n====================================================\n";
        print shift @array;
    }
} else {
    print "Mailbox is empty.\n";
}

# close connection
$conn->quit();
close($email_file) or die "Error closing Mail.txt from write: $!";
  • Eliminé la predeclaración de variables.
  • Cambié las dos aperturas para usar paréntesis y verificar errores.
  • Me moví declarando y configurando @array justo después de que se abra out.txt.
  • Ya que $ random_file no es necesario después de configurar @array, lo cierro en la siguiente línea.
  • Por último, verifico si hay errores al cerrar Mail.txt que se abrió para escribir. Es muy importante verificar el valor de retorno de cerrar en un archivo que abrió para escribir, ya que ciertos errores, como quedarse sin espacio en el disco mientras se escribe en el archivo, no se verán en la apertura inicial, sino que se verán al verificar que cerrar ($ fh) devuelto verdadero.

Todavía hay espacio para mejorar, pero esos eran los grandes. Sin embargo, debo decir que su código fue un buen comienzo para alguien nuevo en Perl. Usando estricto y advertencias, el bucle foreach para iterar sobre las claves del hash, así como Getopt :: Long vs tratando de analizar los argumentos de la línea de comandos, es bueno verlo.

Otros consejos

Esta es la línea que está causando el problema.

my @array = shuffle(<$random_name>);

Debe definir $ random_name antes de usarlo. Intenta

open my $random_name, "<", "out.txt";
my @array = shuffle(<$random_name>);

En la línea 17, $ random_name no está inicializado todavía. Querrá poner esta declaración después de el archivo $ random_name está abierto (línea 27).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top