in reply to Buffered read and matching

Read the file line for line and use a flag to indicate whether you want to collect lines or not, you could also call it a simple state machine:

my $errormatching=0; my @errortext=''; while (<>) { if (not $errormatching) { $errormatching=1 if m{^\s*'Errors' =>}; } else { if (not m{^\s*\]}) { push @errortext, $_; } else { process_error(@errortext); @errortext=(); $errormatching=0; } } }

UPDATE: Fixed typo where I used [ instead of ] in the regex

Replies are listed 'Best First'.
Re^2: Buffered read and matching
by Perlbotics (Archbishop) on Oct 15, 2008 at 12:35 UTC

    Right, I wanted to suggest some state machine along this too:

    #!/usr/bin/perl use strict; my @lines; sub flush { return unless grep(/'Errors'/, @_); print "Got:\n\t", join ("\t", @_), "\n"; } while (<>) { # trigger on last line of an error message flush(@lines,$_),@lines=(),next if m{^\s*\};\s*$}; # triggger on next timestamp flush(@lines), @lines=() if m{^\s*\[\d\d\d\d\/}; push(@lines, $_); } flush(@lines);
    However, all solutions I have seen so far trigger evaluation with the next timestamp only. When using tail -f, the error will be processed only when the next log-line with a time-stamp is encountered - which might happen some hours or days later. IF seeing an error ASAP is important to the OP, the evaluation should be triggered additionally by matching for }; or by some timeout-mechanism, e.g. using alarm().
    Update: final flush(...) added

      You might have been mislead by a bug in my solution where I used the wrong bracket for end of error detection (which makes the script not work at all), but it does process the error when ] is encountered, i.e. well before the next log-line.