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

I am writing a script to parse log. I am reading each line from the log and if some condition satisfies I want store that line to some buffer variable and I want to use that buffer later. but the problem is when I print buffer later, the value is changed to the last line. here is the snippet.
while (<$fhlog>) { my $line = $_; my $bufferline; if ($line =~ /Finished (.*)\. Wrote (\d+) new, (\d+) duplicates, (\d+) + archived/) { &storeAdapterDetails($1, $2, $3, $4, $fhresult); next; } if ($line =~ /ERROR/) { $bufferline = '$line'; next; } if ($line =~ /.*Exception:/) { print "Found adapter: ".$bufferline; $flag = 1; }

20080916 Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: variable reference problem
by bobf (Monsignor) on Sep 11, 2008 at 03:19 UTC

    Thanks for providing your code, but it's very hard to read without formatting. Please use 'code' tags as described in Writeup Formatting Tips, as follows:

    while (<$fhlog>) { my $line = $_; my $bufferline; if ($line =~ /Finished (.*)\. Wrote (\d+) new, (\d+) duplicates, ( +\d+) archived/) { &storeAdapterDetails($1, $2, $3, $4, $fhresult); next; } if ($line =~ /ERROR/) { $bufferline = '$line'; next; } if ($line =~ /.*Exception:/) { print "Found adapter: ".$bufferline; $flag = 1; }

    Some comments:

    • $bufferline is declared inside the while loop, so any values assigned to it in one iteration will not be available in subsequent iterations (or after the loop is complete).
    • Calling storeAdapterDetails with a leading '&' has consequences (see perlsub). Did you use it intentionally? If not, you may want to remove it to avoid potential bugs in the future.
    • $fhresult is not declared in your example; I assume it is set prior to the loop
    • Single quotes do not interpolate, so $bufferline is getting set to the literal string '$line'. You probably want $bufferline = $line; instead.
    • Using 'next' after assigning to $bufferline prevents evaluation of the following if statement, so the print statement containing $bufferline will not be executed. Furthermore, when that statement is executed, $bufferline will be uninitialized.
    • $flag is not declared in the loop, so I assume it was declared previously
    • Using sequential 'if' statements implies (to me) that it is possible for more than one condition to apply during each iteration. If that is not the case (based on the use of 'next'), 'elsif' may convey more meaning to anyone reading the code.
    • There is nothing wrong with while( <$fhlog> ) { my $line = $_; ... }, but I would write that as while( my $line = <$fhlog> ) { ... }

    Hope this helps

      Hi thanks for your help.
      You cleared many of my doubts.

      Re: 2nd point
      I dont know any difference in calling subroutine with '&' or without '&'. Can you explain me?

      Thanks for the Writing Formatting link. I will follow the standards.

        "&" causes Perl to ignore the sub's prototype.

        Some people use "&" to indicate a user sub, since it can only be used on subs, not on builtin functions. But I think that's a bad idea since "&" is not just decorative.

        You might be interested in reading (tye)Re: A question of style.

Re: variable reference problem
by ikegami (Patriarch) on Sep 11, 2008 at 00:02 UTC
    Your buffer is declared inside the loop, so the variable is cleared after every loop pass, so I find it hard to believe is has *any* value later.