iRemix94 has asked for the wisdom of the Perl Monks concerning the following question:

Hello dear PERL Community!

I am almost done with my PERL project, but I've got a problem with overwriting a hash / array reference. The problem is the @columns_import array. I put a hash reference into it, but the information is getting overwritten everytime. I always get the same import time. Any tip how to not overwrite the entries?

Here's the code:

for my $customer (keys %$bi) { #print "<$customer>\n"; if($tr_bgcolor==1) { $tr_bgcolor=0; } else { $tr_bgcolor=1; } for my $domain (keys %{$bi->{$customer}}) { # print " <$domain>\n"; my %data_structure; my @schedule_rows_loop; my @schedule_columns_loop; my @imp_exp_status_loop; $data_structure{CUSTOMER}=$customer; $data_structure{DOMAIN}=$domain; for my $host (keys %{$bi->{$customer}->{$domain}}) { my $schedule = $bi->{$customer}->{$domain}->{$host}->{BACK +UPCFG}->{EXPORT_SCHEDULE_1}->{VALUE}; if (defined $schedule) { my $import_value=$bi->{$customer}->{$domain}->{$host}- +>{BACKUPCFG}->{IMPORT_ACTIVE_1}->{VALUE}; my $export_value=$bi->{$customer}->{$domain}->{$host}- +>{BACKUPCFG}->{EXPORT_ACTIVE_1}->{VALUE}; my $scheduled_export_days =convert_seconds_days(($bi-> +{$customer}->{$domain}->{$host}->{BACKUPCFG}->{EXPORT_BACKUP_LIFETIME +_SEC_1}->{VALUE})); $data_structure{IMPORT_VALUE}=$import_value; $data_structure{EXPORT_VALUE}=$export_value; my @unsorted_schedule=split(/,/, $schedule); my @schedule= sort {$b <=> $a} @unsorted_schedule; + for my $schedule_hour ( @schedule ) { my @columns_export; my @columns_import; foreach my $i ( 1 .. $scheduled_export_days ) { my %column_data_export; my %column_data_import; $column_data_export{SCHEDULE} = $schedule_hour +; $column_data_export{UNDEF} = 1; for my $act (@{$bi->{$customer}->{$domain}->{$ +host}->{BACKUPDATA}}) { my $imp_exp_type= ($act->{ACTION_TYPE}); my $imp_exp_status= ($act->{STATUS}); my @schedule_time = split(/:/, $schedule_ +hour); my $minutes_range = (@schedule_time[1]+30) + % 60; if($imp_exp_type eq "IMPORT") # +#### -> Here's the relevant part { # print Dumper(\%column_data_import)."\ +n"; my $endtime_sec = ($act->{ENDDATE_SEC} +); my $import_start = $unit->formatDateTi +me ($endtime_sec); my @imp_start = split(/ /,$import_star +t); my @imp_hours_unformated = split(/:/, +@imp_start[1]); my $imp_hour = "@imp_hours_unformated[ +0]"; my $imp_minutes ="@imp_hours_unformate +d[1]"; my $imp_formated_hour ="$imp_hour:$imp +_minutes"; $column_data_import{SCHEDULE} = $imp_f +ormated_hour; $column_data_import{UNDEF} = 1; } if($imp_exp_type eq "EXPORT") { my $startdate_sec = ($act->{STARTDATE_ +SEC}); my $export_start = $unit->formatDateTi +me ($startdate_sec); my @exp_start = split(/ /,$export_star +t); my @exp_hours_unformated = split(/:/, +@exp_start[1]); + my $exp_date = @exp_start[0]; my $exp_hour = "@exp_hours_unformated[ +0]"; my $exp_minutes ="@exp_hours_unformate +d[1]"; if ($exp_date eq @localtime_date[$i-1] + and $exp_hour eq @schedule_time[0] and $exp_minutes <= $minutes_rang +e) + + { + + + + #my $link =$customer."_".$domain." +_".@localtime_date[$i-1]."_".$exp_hour."_".$imp_exp_type.".html"; + my $link =$customer."_".$domain."_ +".@localtime_date[$i-1]."_".$exp_hour."_".$imp_exp_type.".html"; + + + $column_data_export{LINK} =$link; if( $imp_exp_status eq "OK") { $column_data_export{OK} = 1; + $column_data_export{UNDEF} = 0 +; } elsif( $imp_exp_status eq "FAILED" +) { $column_data_export{FAILED} = +1; $column_data_export{UNDEF} = 0 +; } } elsif( @localtime_date[0] eq @localtim +e_date[$i-1] and $hour eq @schedule_time[0] and $min <= $minutes_rang +e and $column_data_export{UNDEF} = 1) { $column_data_export{RUNNING} = 1; $column_data_export{UNDEF} = 0; } } } push (@columns_export, \%column_data_export); + push (@columns_import, \%column_data_import); } if($scheduled_export_days!=7) { my $rest_days = 7-$scheduled_export_days; for ( 1 .. $rest_days) { push (@columns_import, { SCHEDULE => '&nbs +p;', UNDEF => '1'}); push (@columns_export, { SCHEDULE => '&nbs +p;', UNDEF => '1'}); } } push ( @schedule_rows_loop, { SCHEDULE_COLUMNS_EXP +ORT => \@columns_export } ); push ( @schedule_rows_loop, { SCHEDULE_COLUMNS_IMP +ORT => \@columns_import } ); } } } $data_structure{BGCOLOR_CUSTOMER}= $tr_bgcolor; $data_structure{SCHEDULE_ROWS} = \@schedule_rows_loop; push (@data_structure_loop, \%data_structure); my $dumper_file = Dumper(\@data_structure_loop)."\n"; open(my $fh, '>', $log); print $fh "$dumper_file"; close $fh; print Dumper(\@data_structure_loop)."\n"; } } $template->param(DATA_STRUCTURE => \@data_structure_loop); my $overview_output= $template->output; open(my $fh, '>', $overview_location); print $fh "$overview_output"; close $fh;

That's what the Dumper gives me for a relevant entry:

{ 'IMPORT_VALUE' => '1', 'BGCOLOR_CUSTOMER' => 0, 'SCHEDULE_ROWS' => [ { 'SCHEDULE_COLUMNS_EXPORT' => [ { 'S +CHEDULE' => '20:00', 'U +NDEF' => 1 }, { 'L +INK' => 'CUSTOMERA_DOMAINA_27.07.2015_20_EXPORT.html', 'O +K' => 1, 'S +CHEDULE' => '20:00', 'U +NDEF' => 0 }, { 'L +INK' => 'CUSTOMERA_DOMAINA_26.07.2015_20_EXPORT.html', 'O +K' => 1, 'S +CHEDULE' => '20:00', 'U +NDEF' => 0 }, { 'L +INK' => 'CUSTOMERA_DOMAINA_25.07.2015_20_EXPORT.html', 'O +K' => 1, 'S +CHEDULE' => '20:00', 'U +NDEF' => 0 }, { 'S +CHEDULE' => '20:00', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '20:00', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '20:00', 'U +NDEF' => 1 } ] }, { 'SCHEDULE_COLUMNS_IMPORT' => [ { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 }, { 'S +CHEDULE' => '23:42', 'U +NDEF' => 1 } ] } ], 'EXPORT_VALUE' => '1', 'DOMAIN' => 'DOMAINA', 'CUSTOMER' => 'CUSTOMERA' },

Replies are listed 'Best First'.
Re: Overwriting Hash / Array
by Corion (Patriarch) on Jul 28, 2015 at 07:55 UTC

    The variable @columns_import is only declared within your 1..$scheduled_export_days loop and will be initialized anew on every trip through that loop.

    A different variable of the same name is used outside of that loop.

    Either you are not using the strict pragma, which would have alerted you to the situation of an undeclared variable being used, or you have declared the variable in two places.

      I'm sorry, that was something I changed before to try some things, I updated the code so it reflects exactly how it works at the moment! The @columns_import array should be outside of the named loop, you are right. Do you have any idea how to get the overwritten array fixed?

        The @columns_import array is not the problem. You are modifying the %column_data_import; hash but always keep the same variable around. Most likely, the line my %column_data_import; must be moved into the loop where the different column data import schedules are held.

Re: Overwriting Hash / Array
by kcott (Archbishop) on Jul 28, 2015 at 09:51 UTC

    G'day iRemix94,

    I see you found out what the problem is.

    "Any tip how to not overwrite the entries?"

    Yes.

    Change lines that look like this:

    push @array, \%hash

    To lines that look more like this:

    push @array, {%hash}

    Similarly, change '\@array' to '[@array]', where appropriate.

    — Ken

      sadly, I still don't know how to fix the proplem .. As I've understood it, I have to declare the hash inside the loop that gets the information, but with it, I have to put the "push" line into that loop aswell, which gives me not the wished output.

        I've refactored your code slightly and I hope you can see how the act loop is setting the same hash element each time. Add the $debug variable to see. What structure do you want ?

        foreach my $i ( 1 .. $scheduled_export_days ){ my %column_data_export; my %column_data_import; $column_data_export{SCHEDULE} = $schedule_hour; $column_data_export{UNDEF} = 1; my $debug=0; for my $act (@{$bi->{$customer}->{$domain}->{$host}->{BACKUPDATA}}){ + ++$debug; my $imp_exp_type = $act->{ACTION_TYPE}; my $imp_exp_status = $act->{STATUS}; my @schedule_time = split(/:/, $schedule_hour); my $minutes_range = ($schedule_time[1]+30) % 60; # import code if ($imp_exp_type eq "IMPORT"){ my ($imp_formated_hour,undef) = hhmm($act->{ENDDATE_SEC},$unit) $column_data_import{SCHEDULE} = $imp_formated_hour; $column_data_import{UNDEF} = $debug ;#1 ; } # export code } push (@columns_export, \%column_data_export); push (@columns_import, \%column_data_import); } sub hhmm { my ($s,$unit) = @_; my @tmp = split / /,$unit->formatDateTime($s); my ($hr,$min) = split /:/, $tmp[1]; return ("$hr:$min",$tmp[0]); }
        poj