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

Thanks in advance for any and all assistance. My issue is I want to parse through a text file and get a SQL error message, I can get the regex to match on the "SQL" but then I want to capture the message to the end of the next line. Here is my code so far:

while (my $line = <FILE>) { if($line =~ /SQL/) { chomp($date = `date`); chomp ($errcode = $line); print ERR "$date - $errcode\n"; } }

Here is a sample input file:

Sun Sep 19 10:34:29 2010
Online Backup for GMT failed.
SQL2033N An error occurred while accessing TSM during the processing of a
database utility. Reason code: 1.

So what I want returned is:
SQL2033N An error occurred while accessing TSM during the processing of a
database utility. Reason code: 1.

So I can match and return the line that has "SQL" but I can't figure out how to return the line underneath it becuase that line doens't have anything consistent, in fact there may not even be anything on that line depending on the error.

I just can't figure out how to get this to return the next line in the file to the end of that line along with the line that I matched with the REGEX.

Thanks -- bp4a

Replies are listed 'Best First'.
Re: Regex to end of a line from previous line
by Corion (Patriarch) on Sep 23, 2010 at 15:12 UTC

    Maybe you don't need to know where the current (error) message ends, but just need to know where the next message starts?

    Showing us some more lines of input (also in between <code>...</code> tags) might help us help you better. If the current message ends with a blank line, the following could be all you need:

    while (<FILE>) { if (/^SQL/ .. /^$/) { print "Found error $_\n"; }; };

    Also, instead of shelling out to date, I prefer POSIX::strftime, or localtime.

      Corion -- The file is overwritten each time there is an error, so there won't be a next error listed. This file just stores the error and sends that info in an email to us, then when it fails the next time it is overwritten with the new error message. I am just trying to get a history of the errors to show my TSM group what I am seeing with my DB backups. But without all the "online backup of blatty blah failed etc."

      Not sure if I am going to change the way I get the date/time stamp cause this is how we already capture this info in all the other scripts on all the other servers and it would probably be too much of a hassle to mess with right now. Thanks for the tip and response.

      Thansk -- bp4a

        So, how do you know that one message ended and the next message starts, then?

Re: Regex to end of a line from previous line
by moritz (Cardinal) on Sep 23, 2010 at 15:18 UTC
    Try something like this:
    while (my $line = <FILE>) { if($line =~ /SQL/) { chomp($date = `date`); chomp ($errcode = $line); print ERR "$date - $errcode\n"; }#end of if }#end of while

    P.S. good indenting makes the # end of $something comments superfluous, and increases readability.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Regex to end of a line from previous line
by kennethk (Abbot) on Sep 23, 2010 at 15:39 UTC
    There are two solutions that come to mind for you.
    1. You could use a persistent flag to create a state machine. All this means is you set a variable to true every time you see a line with "SQL". When you read in a line and the flag is true, you flip it and output that line. Something like:

      use strict; use warnings; my $flag = 0; while (my $line = <DATA>) { if ($flag) { print $line; $flag = 0; } if($line =~ /SQL/) { chomp(my $date = `date`); chomp (my $errcode = $line); print "$date - $errcode\n"; $flag = 1; }#end of if }#end of while __DATA__ Sun Sep 19 10:34:29 2010 Online Backup for GMT failed. SQL2033N An error occurred while accessing TSM during the processing o +f a database utility. Reason code: 1.
    2. You could change your default record separator ($/), and use multi-line regular expressions (Modifiers) with capturing (Extracting matches) to extract the text you want. This is usually closer to how I end up doing this sort of thing, but is dramatically more complex.

    As a side note, please wrap input and expected output in code tags as well as your code. It makes downloading it easier, and more importantly, it helps us make sure our regular expressions actually match what you mean, not what's written. See Writeup Formatting Tips.

      Thanks for the help and tips on posting here! I am just going to use the $rc (the actual error) that is used to write to the file that I was trying to read from and avoid the whole mess of multiline regex and write out the error message and time! Sorry for wasting your time on this, my fault for not seeing this variable.

      Thanks -- bp4a