in reply to Re: Print line from file only once even if occurrence of pattern is more than once in the line
in thread Print line from file only once even if occurrence of pattern is more than once in the line

Thanks Rolf. You are right. The code snippet is as below:
my @log_patterns = ( qr/ERROR/, qr/Error/, qr/FATAL/i, qr/critical/i, ); my @log_lines=<$read_tmp_log>; my $i; my $j; for (@log_patterns){ for $i (0..$#log_lines) { next unless $log_lines[$i] =~ $_; my $a = $i - 5 < 0 ? 0 : $i - 5;; my $b = $i + 5 > $#log_lines ? $#log_lines : $i + 5; print $output_file "\n"; for $j($a..$b){ print $output_file $log_lines[$j]; } } }
  • Comment on Re^2: Print line from file only once even if occurrence of pattern is more than once in the line
  • Download Code

Replies are listed 'Best First'.
Re^3: Print line from file only once even if occurrence of pattern is more than once in the line
by pme (Monsignor) on Mar 29, 2015 at 18:10 UTC
    Hi jayu_rao,

    Try to do this way:

    while(<$read_tmp_log>) { # reads input line if ( /error|fatal|critical/i ) { # if the line contains error, fata +l or critical case insensitively ... # process data } }
      Thanks pme. Reason why I used two for loops is that I need to print 5 lines before and after the pattern occurrence and I did not know how I could achieve it using while loop as per your suggestion.

      I tried earlier as well but in vain. Could you or anyone please help in shedding some more light on it, if you are aware?

      Regards,

      Jay

      Thanks pme. That had just three lines before the occurrence of a pattern. My requirement is something like this: The line could have text such as: "ERROR - Critical error" or "ERROR - <module> threw an error" or "FATAL - Fatal error" or "java.lang.OutOfMemoryError" and I needed 5 lines before the matched line, matched line and 5 lines after the matched line to be printed. Note that the lines could occur immediately after one another and I would like to have output print only once in such cases.
        Note that the lines could occur immediately after one another and I would like to have output print only once in such cases.

        To avoid this, a solution using vec could work for you.

        The line of code vec($vec, $_, 1) ||= 1 for $lo .. $hi; would assign a 1 to each position. So you wouldn't repeat a line when printing out the results.

        my @log_lines=<$read_tmp_log>; my $vec = ''; for my $i (0..$#log_lines) { next unless lc($log_lines[$i]) =~ /error|fatal|critical/; my $lo = $i - 5 < 0 ? 0 : $i - 5;; my $hi = $i + 5 > $#log_lines ? $#log_lines : $i + 5; vec($vec, $_, 1) ||= 1 for $lo .. $hi; } my $newline_needed = 0; for my $i (0 .. $#log_lines) { if (vec($vec, $i, 1) == 1) { print $log_lines[$i]; $newline_needed ||= 1; } else { print "\n" if $newline_needed; $newline_needed = 0; } }
Re^3: Print line from file only once even if occurrence of pattern is more than once in the line (double?)
by LanX (Saint) on Mar 29, 2015 at 18:38 UTC
      Appreciate everyone's responses so far. The difference is subtle. In my earlier post, the output needed to have 5 lines before and after each occurrence of a pattern but now in this thread, I want the output to have 5 lines before the pattern, the matched line to be printed only once even if there are multiple occurrences of same pattern or different patterns within same line and 5 lines after the matched line. I hope I am able to express the difference.