kayama kayama - 2 months ago 28
Perl Question

Perl error Use of uninitialized value $_ in substitution (s///)

Greeting I try to read a file into hash of hash following this tutorial.

http://docstore.mik.ua/orelly/perl/prog3/ch09_04.htm

My text input file is

event_a1_x1: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3
event_a1_x2: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3
event_b2_y1: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3
event_b2_y2: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3
event_c3_z1: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3
event_c3_z2: email1=xxx@gmail.com email2=yyy@gmail.com email1_cnt=3


My code is

#!/usr/bin/perl
use strict;
use warnings;

my $file = $ARGV[0] or die "Need to get config file on the command line\n";

open(my $data, '<', $file) or die "Could not open '$file' $!\n";

my %HoH;
#open FILE, "filename.txt" or die $!;
my $key;
my $value;
my $who;
my $rec;
my $field;

while ( my $line = <$data>) {
print $line;
next unless (s/^(.*?):\s*//);
$who = $1;
#print $who;
$rec = {};
$HoH{$who} = $rec;
for $field ( split ) {
($key, $value) = split /=/, $field;
$rec->{$key} = $value;
}
}


I keep getting this error...

Use of uninitialized value $_ in substitution (s///) at ./read_config.pl line 18, <$data> line 1.

Answer

This is about when $_, "the default input and pattern-searching space", is set and used.

In while (<$fh>), what is read from the filehandle is assigned to $_. Then your regex s/// and print and split can use it. See General Variables in perlvar.

However, once we specifically assign to a variable, while (my $line = <$fh>), this deal is off and $_ is not set. So when you later use the regex substitution in a way that relies on $_ the variable is found uninitialized.

Either consistently use the default $_, or (consistently) don't. So, either

while (<$fh>) { 
    print;
    # same as posted
}

or

while (my $line = <$fh>) {
    # ...
    next unless $line =~ s/^(.*?):\s*//;
    # ...
    foreach my $field (split ' ', $line) {
        # ...
    }
}

There is quite a bit more that can be improved in the code, but that would take us elsewhere.