in reply to Re^2: 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

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 } }
  • Comment on Re^3: 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^4: Print line from file only once even if occurrence of pattern is more than once in the line
by jayu_rao (Sexton) on Mar 29, 2015 at 18:22 UTC
    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

Re^4: Print line from file only once even if occurrence of pattern is more than once in the line
by jayu_rao (Sexton) on Mar 29, 2015 at 19:18 UTC
    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; } }