in reply to Perl: How to perfectly match specific data between two files and do comparison?

#!/usr/bin/perl use strict; use warnings; sub readReport { my $filename = shift; my %hash; open (my $file, '<', $filename) or die $!; while (<$file>) { next unless /^--------/ .. eof; # Bypass header if (my ($name, $score) = /^\s*(\S+).+\s(\S+)\s*$/) { $hash{$name} = $score; } } return \%hash; } my $reportA = readReport('filea'); my $reportB = readReport('fileb'); my %reports = ( fail => [], ignored => [], noCheck => [], pass => [] ) +; for my $name (sort keys $reportA) { my @scores = ($reportA->{$name}, $reportB->{$name}); my $rpt = "fail"; if ($scores[0] < 0) { $rpt = defined $scores[1] ? 'noCheck' : 'ignored'; $scores[1] //= 0; } elsif ($scores[0] > 50 and $scores[1] > 40) { $rpt = 'pass'; } push $reports{$rpt}, "$name, @scores"; } for my $name (keys %reports) { print "\nReport $name\n----------------------\n" ; print "$_\n" for @{$reports{$name}}; }
Output:
Report pass ---------------------- Alfert_pipe, 82 57 Report noCheck ---------------------- alan/excel/sa/y589, -70 -90 yuki/099/pipe, -82 82 Report fail ---------------------- Olive_pipe, 58 20 frey/let/sa/y589, 78 30 mass/excel/i60, 68 16 Report ignored ---------------------- Anne_let, -39 0 Jane_let, -33 0

Replies are listed 'Best First'.
Re^2: Perl: How to perfectly match specific data between two files and do comparison?
by WWq (Novice) on Jul 24, 2013 at 08:19 UTC
    Hi Loops, Thanks. What if I want to match name included brackets behind? Some of the names have brackets info such as like (sa)and (tan804k). Those bracket info are needed for name matching. How to match brackets correctly?
      You need to change the regex that pulls the name out of the text, to something like:
      /^\s*(\S+(?:.*\(.*\))?).+\s(\S+)\s*$/
      Okay, here's a slightly updated version that includes that regex, and a minor cleanup:
      use strict; use warnings; sub readReport { my $filename = shift; my %hash; open (my $file, '<', $filename) or die $!; while (<$file>) { next unless /^--------/ .. eof; # Bypass header if (my ($name, $score) = /^\s*(\S+(?:.*\(.*\))?).+\s(\S+)\s*$/ +) { $hash{$name} = $score; } } return \%hash; } my $reportA = readReport('filea'); my $reportB = readReport('fileb'); my %reports = ( fail => [], ignored => [], noCheck => [], pass => [] ) +; for my $name (sort keys $reportA) { my ($a,$b) = ($reportA->{$name}, $reportB->{$name}); if ($a < 0) { push $reports{'noCheck'}, "$name, $a $b" if defined $b; push $reports{'ignored'}, "$name, $a 0" unless defined $b; } elsif ($a > 50 and $b > 40) { push $reports{'pass'}, "$name, $a $b"; } else { push $reports{'fail'}, "$name, $a $b"; } } for my $name (keys %reports) { print "\nReport $name\n----------------------\n" ; print "$_\n" for @{$reports{$name}}; }
        Thank you. It almost works! However, It prints the same scores in reports. Maybe some problem in defining $a and $b or push array. I tried to print out $a and $b after: my ($a,$b) = ($reportA->{$name}, $reportB->{$name}); The output scores are the same from file B. Perhaps I miss out something. What's wrong with that?
        Thank you so much Loops! It works after debugging. =)