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

Hi Monks,

I have a problem with the following code.Can anybody help

The code may be wrong since I am still developing , but the error confuses me.

use warnings; use strict; &readfile; sub readfile{ my $input_FL;my @file_row;my @row_text;my $row_data;my $row_text; my $line =0; my $status;my $soc; my $subscriber; my @ar_OR_STA;my @ar_OR_SOC;my @ar_OR_SUB; $input_FL = "C:\\taj.txt"; chomp $input_FL; #remove enter key or any spaces open(IN_FL, $input_FL) || die ("unable to open directory"); while (<IN_FL>){ @file_row=<IN_FL>; print $#file_row; }#while close IN_FL; foreach(@file_row) { while ($line < $#file_row +1){ $row_data =$file_row[$line]; chop ($row_data); next unless /\S/; # only use lines that contain +something else + than spaces #print "$row_data\n"; if ($row_data =~ /^[d]/) { $status = $row_text[0]; $status =~ s/(\W+)/ /gs; #Eliminate all non-+word charac +ters followed by space. #$ar_OR_STA[$i]=$status; #Here $=1, so @ar_STA[0] does no +t have any value. Original Array of Status push (@ar_OR_STA,$status); print "@ar_OR_STA\n"; $soc = $row_text[1]; $soc =~ s/(\W+)/ /; #Eliminate all non-word characters f +ollowed by space. #$ar_OR_SOC[$i-1]=$soc; #Here $=1, so @ar_STA[0] does no +t have any value. Original Array of Status $subscriber = $row_text[3]; $subscriber =~ s/(\D+)/ /; #Eliminate all non-digits foll +owed by space. #$ar_OR_SUB[$i-1]=$subscriber; #Here $=1, so @ar_SUB[0] +does not have any value.Original Array of Subscriber } else { print " File is invalid\n"; } $line++; }#while }#foeach }
Here, I get Uninitaialized value in substitution(s///) in the following lines?Anybody Know why?
$status =~ s/(\W+)/ /gs; $soc =~ s/(\W+)/ /; $subscriber =~ s/(\D+)/ /;
and
use of initialized value in join or string at print "@ar_OR_STA\n";
Any help appreciated

Replies are listed 'Best First'.
Re: Use of Uninitialized value in substitution (s///)
by kyle (Abbot) on Jan 26, 2008 at 22:48 UTC

    The values of $status, $soc, and $subscriber are based on @row_text, but that array is never populated. Each of those scalars will be undef.

    For other interested monks, here's my feeble attempt at reformatting:

    use warnings; use strict; &readfile; sub readfile{ my $input_FL; my @file_row; my @row_text; my $row_data; my $row_text; my $line =0; my $status; my $soc; my $subscriber; my @ar_OR_STA; my @ar_OR_SOC; my @ar_OR_SUB; $input_FL = "C:\\taj.txt"; chomp $input_FL; #remove enter key or any spaces open(IN_FL, $input_FL) || die ("unable to open directory"); while (<IN_FL>){ @file_row=<IN_FL>; print $#file_row; }#while close IN_FL; foreach(@file_row) { while ($line < $#file_row +1){ $row_data =$file_row[$line]; chop ($row_data); next unless /\S/; # only use lines that contain +something + else than spaces #print "$row_data\n"; if ($row_data =~ /^[d]/) { $status = $row_text[0]; $status =~ s/(\W+)/ /gs; #Eliminate all non-+word char +acters followed by space. #$ar_OR_STA[$i]=$status; #Here $[=1, so @ar_STA[0] doe +s not have any value. Original Array of Status push (@ar_OR_STA,$status); print "@ar_OR_STA\n"; $soc = $row_text[1]; $soc =~ s/(\W+)/ /; #Eliminate all non-word characters + followed by space. #$ar_OR_SOC[$i-1]=$soc; #Here $[=1, so @ar_STA[0] does + not have any value. Original Array of Status $subscriber = $row_text[3]; $subscriber =~ s/(\D+)/ /; #Eliminate all non-digits f +ollowed by space. #$ar_OR_SUB[$i-1]=$subscriber; #Here $=1, so @ar_SUB[0 +] does not have any value.Original Array of Subscriber } else { print " File is invalid\n"; } $line++; }#while }#foeach } # Here, I get Uninitaialized value in substitution(s///) in the follow +ing lines?Anybody Know why? $status =~ s/(\W+)/ /gs; $soc =~ s/(\W+)/ /; $subscriber =~ s/(\D+)/ /; # and use of initialized value in join or s +tring at print "@ar_OR_STA\n";

    As an aside, I think changing the value of $[ could have some very confusing unwanted consequences later in this code's life. (I quote perlvar: "Its use is highly discouraged.") If you must go through with that, use local to limit the scope (although I can't tell that you haven't from the code you posted).

      Perl is crazy. if you put a space after the "=", you will get this error. Something like this: $s = ~s/abc/def/g; This is ridiculas.

        That's not "putting a space after the =", that's breaking the =~ operator by spelling it wrong. Crazy? What's crazy is thinking that putting spaces in the middle of operators should have no effect. Thinking = ~ should work is as crazy as thinking that e q should work, or s ub, or m y.

Re: Use of Uninitialized value in substitution (s///)
by hipowls (Curate) on Jan 26, 2008 at 22:28 UTC

    I suggest that you have a look at Writeup Formatting Tips which tells you how to format your questions. The bottom of the preview page has a quick guide to available tags and some handy links.

    You will get a better response if your questions are well presented. At a minimum use <p> </p> pairs for paragraphs and <code> </code> for literal code or data blocks.

    Once you have reformatted your question I will have a look at it;-)

Re: Use of Uninitialized value in substitution (s///)
by hipowls (Curate) on Jan 26, 2008 at 23:32 UTC

    Well done kyle! I should have realised that [ and ] were being interpreted as link metacharacters.

    There are a number of odd things about this script. I'll start with a couple of minor points, The code and comments in these lines are contradictory

    $status =~ s/(\W+)/ /gs; #Eliminate all non-word characters followed b +y space.
    Actually replaces all groups of non word characters with a single space.
    $soc =~ s/(\W+)/ /; #Eliminate all non-word characters followed by spa +ce.
    Replaces first group of non-word characters with a single space.
    $subscriber =~ s/(\D+)/ /; #Eliminate all non-digits followed by space +.
    Replaces first group of non-digit characters with a single space.

    The more egregious error is the logic is badly flawed. This nested loop

    foreach (@file_row) { while ( $line < $#file_row + 1 ) { $row_data = $file_row[$line]; # Processing goes here. $line++; } #while } #foreach
    should be written as
    foreach $row_data ( @file_row ) { # Processing goes here. }
    Unless @file_row was used elsewhere I would eliminate reading the entire file and do it a line at a time like so
    while ( $row_data = <IN_FL> ) { # Processing here }
    Actually I doubt that we were given the irreducible minimum to reproduce the problem so I think @file_row is only used here and should be eliminated.

    Update: I'd also change

    open(IN_FL, $input_FL) || die ("unable to open directory");
    to
    open IN_FL, $input_FL or die "unable to open $input_FL:$!";
    You are not opening a directory and it will help debugging if you print the reason you can't open the file.

Re: Use of Uninitialized value in substitution (s///)
by Anonymous Monk on Jan 26, 2008 at 23:12 UTC
    *Sigh* Put <code\>...</code> tags around your code
Re: Use of Uninitialized value in substitution (s///)
by umasuresh (Hermit) on Apr 16, 2010 at 20:11 UTC
    In my experience it always help to visualize the data structure that I am growing be it an array or a hash using the following:
    use Data::Dumper; ... print Dumper(\@array); # OR print Dumper(\%hash);
    This has helped me to fix the problem very quickly.
Re: Use of Uninitialized value in substitution (s///)
by Anonymous Monk on Apr 16, 2010 at 15:13 UTC

    I had the same problem and just fixed it! The problem is the initial assignment of the variables.

    e.g.

    my $status = $myhash{'key1'}; $status =~ s/\t/ /g;

    will give an error IF the value of $myhash{'key1'} is not defined.

    This was my fix:

    my $status = $myhash{'key1'} || ''; $status =~ s/\t/ /g;

    no more error!