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

Try to do manipulation in each file in incremental order. Below is my code n it's giving an error message.

Use of uninitialized value $lines[0] in substitution (s///) at

Use of uninitialized value $lines1 in substitution (s///) at

As m new in Perl World kindly help.

#!/usr/bin/perl -w use strict; use warnings; use 5.010; use autodie; use Time::Piece; use Time::Seconds qw/ ONE_MINUTE /; use constant DATE_FORMAT => '%Y%m%d%H%M%S'; my $n; my $directory="/home/tt/Doc/Auto"; opendir(DIR, $directory) or die "couldn't open $directory: $!\n"; my @files = readdir DIR; foreach (@files) { open my $in_fh, '<', $_; my @lines = <$in_fh>; close $in_fh; ++$n; $lines[0] =~ s/4947000219\K(4947000219+)/$1+$n/e; $lines[1] =~ s{:20140924105028\K(\d+)}{ my $tp = Time::Piece->strptime($1, DATE_FORMAT); ($tp + ONE_MINUTE * 2 * $n)->strftime(DATE_FORMAT); }e; my $backup = "$_.backup"; unlink $backup if -f $backup; rename $_, $backup; open my $out_fh, '>', $_; print $out_fh @lines; close $out_fh; } closedir DIR;
  • Comment on Error "Use of uninitialized value $lines[0] in substitution (s///) at " with below Code
  • Download Code

Replies are listed 'Best First'.
Re: Error "Use of uninitialized value $lines[0] in substitution (s///) at " with below Code
by Anonymous Monk on Dec 11, 2014 at 21:00 UTC
    readdir returns such files as '.' and '..'
    opendir my $dir, './var'; say join "\n", readdir $dir;
    Output:
    fonts.tar.gz . c ..
    Reading this stuff yields nothing:
    open my $file, '<', '.'; my @lines = <$file>; say join "\n", @lines; say scalar @lines;
    Produces empty line and 0.

    Use glob instead...

Re: Error "Use of uninitialized value $lines[0] in substitution (s///) at " with below Code
by RichardK (Parson) on Dec 12, 2014 at 00:41 UTC

    If you put print "$_\n"; at the top of your for loop you'll see what's going on.

    readdir returns the file names without the path of the directory you opened, so you've got to open "$dir/$_" as well as skipping any directories.

    I generally find glob much easier and quicker to use than readdir.

Re: Error "Use of uninitialized value $lines[0] in substitution (s///) at " with below Code
by james28909 (Deacon) on Dec 11, 2014 at 23:12 UTC
    Like already said, you are trying to open '.' and '..' as a file, and its NOT.

    Try this:
    foreach (@files) { next if( -d $_); open my $in_fh, '<', $_; ...rest of code... }
    EDIT: Also, I would personally change the code so you are only opening the outfile once and closing it once scanning the dir is complete. Open it, scan dirs, then close it. Also the way you are opening the outfile '>' in the foreach loop, it will knock out/delete the contents foreach file in said directory, so in essence you will only have data from the last file in the outfile. Maybe that is what you want though.

    Opening it with '>' would be fine if it were opened before of the foreach loop and closed after the foreach loop.
Re: Error "Use of uninitialized value $lines[0] in substitution (s///) at " with below Code
by davido (Cardinal) on Dec 11, 2014 at 20:21 UTC

    If you change line 21 from this:

    open my $in_fh, '<', $_;

    .. to this...

    open my $in_fh, '<', $_ or die $!;

    ... you may see an error message telling you that a file failed to open. If that's the case, you would have to decide whether it's worth continuing on to the next file instead, or whether you should terminate immediately.

    Next, you should test @lines to see how many elements it holds. If it's empty, it is possible you were reading an empty file. If that's the case, you would probably want to skip further processing on the file. And again you would have to make the decision whether to log a warning or die.

    Update: toolic correctly pointed out to me that the OP is using autodie, so my suggestion for "or die $!" is superfluous. Those who mentioned that readdir returns a list of everything including such non-files as ./ and ../ are correct.


    Dave