in reply to Combining Files using Hash

G'day chaney123,

The reason you're getting a warning is because the regex isn't matching. You're sort of on the right track with the construct you used:

$ perl -wE 'my ($x, $y) = "AB" =~ /(.)(.)/; say "$x $y"' A B

However, if the regex doesn't match, you won't populate those variables:

$ perl -wE 'my ($x, $y) = "AB" =~ /(.)(.)./; say "$x $y"' Use of uninitialized value $x in concatenation (.) or string at -e lin +e 1. Use of uninitialized value $y in concatenation (.) or string at -e lin +e 1.

There are some other issues; however, the main one is that a regex is not the right tool for this job — Text::CSV is what you should be using when working with CSV data (if you also have Text::CSV_XS installed, it will run faster).

Here's a quick example I knocked up to show you how much simpler it is when you use the correct tool for the job.

#!/usr/bin/env perl -l use strict; use warnings; use Text::CSV; use Inline::Files; my %data; my $csv = Text::CSV::->new; while (my $row = $csv->getline(\*FILE2)) { $data{$row->[0]} = [ @$row[1..$#$row] ]; } while (my $row = $csv->getline(\*FILE1)) { next unless exists $data{$row->[0]}; push @{$data{$row->[0]}}, $row->[1]; } $csv->print(\*STDOUT, [$_, @{$data{$_}}]) for sort keys %data; __FILE1__ an_en11,200.00,{0 133},{ } br_gh13,140.09,{0 59},{ } ce_oy74,300.05,{0 230},{int_43} dt_pp50,200.11,{0 122},{ } er_tk02,305.47,{0 220},{ } ef_yb41,200.05,{0 233},{ } __FILE2__ dt_pp50,0,0,2,0.000,0.000,0,0.000 er_tk02,0,2,3,0.002,0.004,0,0.001 ef_yb41,0,1,5,0.000,0.000,0,0.000

Output:

dt_pp50,0,0,2,0.000,0.000,0,0.000,200.11 ef_yb41,0,1,5,0.000,0.000,0,0.000,200.05 er_tk02,0,2,3,0.002,0.004,0,0.001,305.47

For demonstration purposes, I've used Inline::Files. You'll want to replace \*FILE1, \*FILE2 and \*STDOUT with your two input and one output filehandles. You're using open correctly, but I would recommend that the names for the filehandles reflect what they really are: $file1, for instance, suggests an actual file (i.e. it holds a filename); $in1_fh is more descriptive (although, the choice of name is entirely yours). I'd also recommend you either: improve the die messages (which are pretty crappy as currently shown), which is more work for you and prone to error; or you remove them and get Perl to do the work for you with the autodie pragma (which would be my choice).

When you do actually have a reason to use a regex, I'd suggest you first read "perlretut - Perl regular expressions tutorial". The fact that you've used the 'g' modifier twice, when it wasn't appropriate, suggests that you're copying code from elsewhere without understanding what it does; even if that's not the case, you still need to understand every piece of code you write — we're always happy to help if you can't work something out for yourself.

— Ken

Replies are listed 'Best First'.
Re^2: Combining Files using Hash
by chaney123 (Acolyte) on Sep 05, 2017 at 07:04 UTC
    Hi Ken,

    I tried using your way to output the result. However, it shows "Can't call method "getline" on an undefined value at reformat_rpt.pl". What does this mean?

    Thanks

      Please take a look at the "How do I post a question effectively?" guidelines.

      Posting the error message, without showing the code that generated it, is completely pointless. All anyone can do is guess! My guess is that you wrote code like this:

      $ perl -e 'use Text::CSV; my $csv; $csv->getline' Can't call method "getline" on an undefined value at -e line 1.

      Possibly a very poor guess, but at least I've replicated your reported error message and shown the code that caused it.

      — Ken