-1

I have a script tha ttake as inputs two files :

  • An extraction of 200k lines
  • The source file

I have to compare extraction against source : each line of the extraction should be in source. If not, I have to log the line a log file.

Below the script :

#!/perl/bin/perl
use strict;
use warnings;
use feature 'say';
# Open log file
open(LOG, '>', 'log.txt');
# Start log
say LOG '['.localtime().'] Début execution';
# Declare extraction number of line counter
my $i_extraction_counter = 1;
# Define files to be compared (extraction against source)
my ($extraction_file, $source_file) = @ARGV;
# Open extraction file
open my $f_extraction, "<", $extraction_file;
# Store extraction file in a hash
my %h_extraction;
while(defined(my $extr_line = <$f_extraction>)){
    $h_extraction{$extr_line} = $extr_line;
    $i_extraction_counter++;
}
# Declare temp hash and counter
my %h_tmp = {};
my $i_counter = 1;
# Open source file
open my $f_source, "<", $source_file;
# For each source line, compare against extraction hash
while(defined(my $source_line = <$f_source>)){
    # If the current line exists in extration hash, stores it in the temp hash & increase counter
    if(defined($h_extraction{$source_line})){
        $h_tmp{$source_line} = $source_line;
        $i_counter++;
    }
    # TO DO : check in elsif if the line should be stored in log (name + firstname OR contract number)
}
# If not all lines of extraction has been stored in temp hash = some lines of extraction are not in source file
if($i_counter < $i_extraction_counter){
    # Declare a second temp hash (used to log missing lines)
    my %h_missing_lines = %h_extraction;
    # For each line of extraction, check if it exists in the first temp hash. If yes, unset it. Only missing line will remain
    foreach my $s_line (keys(%h_missing_lines)){
        if(defined($h_tmp{$s_line})){
            delete($h_missing_lines{$s_line});
        }
    }
    # For each line of missing lines hash, stores it in log file
    foreach my $s_line (keys(%h_missing_lines)){
        say LOG 'Ligne d\'extraction non présente dans fichier source : '.$s_line;
    }
}
say LOG '['.localtime().'] Fin execution';

At the execution, this message shows up : Reference found where even-sized list expected at script.pl line 22, <$f_extraction> line 200000.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
VeZoul
  • 500
  • 6
  • 19
  • 3
    This is a good example of a case where `use diagnostics` does a particularly good job of explaining the problem. Try `perl -Mdiagnostics -E'my %h = {}'`. – Dave Cross Aug 03 '16 at 14:16
  • 1
    @DaveCross: I agree, but `use diagnostics` in the program will spew vast amounts of useless words. Used as `perl -Mdiagnostics` in the same way you might use `perl -d` is essential. Just keep it out of the code. – Borodin Aug 03 '16 at 16:17
  • Good use for PERL5OPT :-) – Dave Cross Aug 03 '16 at 16:43

1 Answers1

15

On line 22, we have:

my %h_tmp = {};

Change that to:

my %h_tmp;

And you will be fine.

The problem here is - {} is used to define an anonymous hash - and return a reference.

So you could do:

my $hash_ref = {}; 

And that's effectively what you're doing.

my %h_tmp = $hash_ref; 

Initialising a hash with a single value like this, gives exactly the error you are getting, because a hash expects key value pairs.

You could do:

my %h_tmp = (); 

This would work, but would be redundant - you're creating an empty hash either way.

Sobrique
  • 52,974
  • 7
  • 60
  • 101