perl - strawberry - Número impar de elementos en la asignación de hash con el valor predeterminado
perl tutorial (2)
Saludo, querida comunidad.
Estoy tratando de crear un sub
en perl que tome un hash y un indicador de depuración que por defecto es cero. Sin embargo, sigo recibiendo este error Odd number of elements in hash assignment
. Si no uso el indicador de depuración, parece que funciona.
Gracias por toda la ayuda.
Código:
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use POSIX qw(strftime);
#
#file2hash : read the file in k<file_name> e.g.=kconfig & kmem into hash table
#
sub file2hash {
my ($file) = @_;
open(my $data, ''<'', $file) or die "Could not open ''$file'' $!/n";
my %HoH;
my $key;
my $value;
my $who;
my $rec;
my $field;
#while ( my $line = <$data>) {
while ( <$data>) {
#print $line;
next unless (s/^(.*?):/s*//); # / turn off editor coloring
$who = $1;
#print $who;
$rec = {};
$HoH{$who} = $rec;
for $field ( split ) {
($key, $value) = split /=/, $field;
$rec->{$key} = $value;
}
}
return %HoH;
}
#
#end file2hash
#
#
#print out hash table in k<file_name> format
#
sub hash2print{
(my %HoH,my $debug) = @_;
#my ($debug)=@_||0;
#my %HoH = shift;
#my $debug = shift || 0;
my $family;
my $role;
for $family ( keys %HoH ) {
#print "$family/n";
for $role ( keys %{ $HoH{$family} } ) {
if ($debug){
print "family:$family/n";
print "role: $role/n";
}
print "$role=$HoH{$family}{$role}";
}
print "/n";
}
}
#
#end hash2print
#
sub dispatch{
my $inc= shift;
my $config_f = shift || "kconfig";
my $memory_f = shift || "kmem";
my %h2=&file2hash($config_f);
my %m2=file2hash($memory_f);
my $today=&getDate();
print "$today/n";
print "$inc/n";
my $inc_cnt = $m2{$today}{$inc} || -999999999;
print "$inc_cnt/n";
#my %config = shift;
#my %mem = shift;
#my $event = shift;
#print $m2{$inc}{$today};
}
sub getDate{
my $date = strftime "%m/%d/%Y", localtime; # "
#print $date;
return $date;
}
my %h2=&file2hash("kconfig");
my %m2=&file2hash("kmem");
&hash2print(%h2,1);
&hash2print(%m2,1);
#print &getDate();
#my $xcnt= &dispatch("event_c3_z2");
#&dispatch("event_c3_z2");
#print $xcnt;
Archivo de prueba1:
event_a1_x1: [email protected] [email protected] email1_cnt=6
event_a1_x2: [email protected] [email protected] email1_cnt=5
event_b2_y1: [email protected] [email protected] email1_cnt=4
event_b2_y2: [email protected] [email protected] email1_cnt=3
event_c3_z1: [email protected] [email protected] email1_cnt=2
event_c3_z2: [email protected] [email protected] email1_cnt=1
archivo de prueba2:
201609230012: event_a1_x1=6
201609230744: event_a1_x2=5
201609230844: event_b2_y1=4
201609230342: event_b2_y2=3
201609230245: event_c3_z1=2
201609230100: event_c3_z2=1
Los argumentos se pasan a una función como una lista plana. Por otro lado, a un hash se le puede asignar una lista, %h = qw(ab)
, donde los elementos consecutivos forman pares clave-valor, $h{a}
es ''b''
. Entonces, cuando un hash es la primera variable que recibe argumentos en una función, los saca a todos. Aquí hay una publicación reciente sobre cómo devuelve una función, donde se aplica exactamente la misma historia.
Entonces todo está asignado al hash, el escalar restante también. Por lo tanto, el hash obtiene un elemento más de lo previsto y termina con un número impar de elementos.
Una solución - en este caso, solo para pasar hash por referencia, como en la respuesta de Inferno
sub hash2print{
my ($rHoH, $debug) = @_;
my %HoH = %$rHoH;
# ...
}
hash2print(/%h2, 1);
En principio, es una buena idea pasar listas por referencia, a menos que sean muy cortas.
En general, puede pasar el escalar primero y luego el hash
sub hash2print{
my ($value, %HoH) = @_;
# ...
}
hash2print(1, %h2);
Pero en su caso esto no funciona, ya que $debug
es opcional, y si lo dejamos fuera al llamar a la función, la primera clave del hash terminaría en $value
.
Algunos otros comentarios
No use globales a menos que haya una razón no negociable para eso. Declarar en pequeño alcance.
No tiene que hacer
$rec = {};
, puede declararlomy $rec;
.En general, no coloque
&
delante de una llamada a función pero use solofile2hash(...)
;
Desea pasar sus valores hash por valor a su subrutina y esto crea el problema. Intente pasar su hash %h2
por referencia en su lugar (observe el /
antes del %
):
&hash2print(/%h2, 1);
Luego, en su sub hash2print
, puede recuperar el hash de la siguiente manera:
sub hash2print {
(my $hashref, my $debug) = @_;
my %HoH = %$hashref; # dereference $hashref to get back the hash
...
Puede leer más acerca de las referencias aquí si no comprende los conceptos detrás de ellas.