in reply to Find data point generating Error in Perl code

Thanks for the update, now it's clear why Perl doesn't automagically know the input file information: You're reading the entire file into @lines, and by the time you write to output.csv, input.csv is already closed.

The quickest fix would be to implement the %SIG __WARN__ handler as described here. Here's a quick example (my input.txt contains just four lines, "foo", "bar", "quz" and "baz"):

open my $infh, '<', 'input.txt' or die $!; my @lines = <$infh>; close $infh; # open output file here my $i; local $SIG{__WARN__} = sub { my $msg = shift; $msg =~ s/\.?\s*$//; warn "$msg (input line $i)\n"; }; for($i=0;$i<@lines;$i++) { # do calculations and write to output file here # example warning: warn "found a z" if $lines[$i]=~/z/; } __END__ # Script Output: found a z at - line 14 (input line 2) found a z at - line 14 (input line 3)

Note that the "line numbers" reported here are 0-based, as it's actually an index into the array of lines. But the advantage is that here, the message is fully customizable, so you're free to print $i+1 or whatever else you like.

However, unless you've oversimplified your example, your code could be made more efficient if it were to keep the input file open while writing the output file. Also, as long as the input file stays open, Perl will normally add the input file line numbers to warning messages by itself. So for example:

open my $infh, '<', 'input.txt' or die $!; # open output file here while( my $line = <$infh> ) { # do calculations and write to output file here # example warning: warn "found a z" if $line=~/z/; } close $infh; __END__ # Script Output: found a z at - line 6, <$infh> line 3. found a z at - line 6, <$infh> line 4.

By the way, your code would be better if you used the three-argument open and error handling (or die), as in the above examples. Also, you really should look into Text::CSV for better handling of CSV files!

Replies are listed 'Best First'.
Re^2: Find data point generating Error in Perl code
by kgherman (Novice) on Mar 17, 2015 at 20:45 UTC
    Thank you, thank you, thank you! Your post is a goldmine of valuable information.

    I have followed your suggestion and now I keep the input file handle open while writing the output. As you had guessed, this allowed me to have the number of the line in the input file added to the warning message! thank you!

    I will definitely look into the Text::CSV module since I only work with CSV files. Also, I will implement the three-argument open and error handling notation.

    I have one last question: I was looking at the last code that you have written in your answer and I was wondering: does your notation mean that you read one line at the time from the CSV file or, like in mine, do you load the entire file in memory and then work on it?

      A while loop over a filehandle like while(my $line = <$fh>) { ... } reads the file line-by-line* (one line is read on each iteration of the loop), as opposed to foreach my $line (<$fh>) { ... } or my @lines = <$fh>;, which reads the entire file first (obviously not particularly friendly on memory for large inputs).

      For more information, see I/O Operators in perlop and readline.

      * Perl's definition of what a "line" is may be changed via the input record separator $/.

      ... since I only work with CSV files.

      Text::CSV!

      I will definitely look into the Text::CSV module...

      Yes! ;-)

        I have decided to change the way my code reads in the data file to make it the way you suggested and it has definitely helped a lot!

        However, using your way, I'm still trying to figure out how to make perl skip the first line in the data file since it contains the names of the variables... what do I need to change in the while loop? thanks!