开发者

trying to isolate a block from my logs with awk, help please!

I am trying to write an awk script that can get a block that contains the word "error", out of a long log file.

Basically this log file contains actions performed, and when one of these fails, it will add under the action the error line, saying what is wrong.

I can isolate easily the error line just doing a grep for "error:", but i am missing the command given since it is printed before the error line, and i do not know how many lines before, so cannot just arbitrarily say "print the 10 lines that precede the word "error:"

I've figured out a sort of scheme thou; each of the block that could contain the error lines starts in the same way ("ProcessName"), followed by the command and other parameters, each one on a different line, and the last line will always be an empty line.

So my idea is to use this block with awk, so i can look for the "processName" string, start to print the lines one by one until i reach the empty line, and then pipe the printed result trough a grep to see if there is the word "error:" in there; if there is an error then i will redirect on a file and append the whole block, otherwise it will continue to the next block and do the same thing.

Now it would really help if i can get a hand with this task; since I do not really know how could I achieve this; I've just looked at awk and it seems to be the right tool for the job (i can write a shell script for the task), but if you think that there is a better way to do it in a shell script, I am all ears :)

Thanks in advance for your help!

Update: Thanks for your scripts; i've got the one from Dennis to work but it prints the same block more than once, if there is more than one error entry in each block; while the example from bellisarius does not return any line.

I've added an example of what my log looks like, when i introduce an error (there is an empty line at the end, but cannot add it if i put the text in the tag code):

ProcessName
ID=1231
Command:"ls -l a"
Hash "gkfsmgflsdmgklsdmfldsmfklmdsflkmsdflmsdflkmsdflkmsdfklsdmfklsdmfklmsdfklmsdklfmsdklmflksdmflkdsmfkldsmfkldmslfmdslkfmklsdmflksdmfklsdmfkldmslfkmslfkmsdlkfm"
/filename/compileme.c:20: error: the directory does not exist
/filename/compileme.c:20: error: incorrect parameter

A re开发者_开发技巧gular block looks exactly the same, but does not have the error: part obviously.

Hope that this makes it more clear, thanks again!


You may try:

BEGIN                {flag="no";k=0}

/ProcessName/        {flag="no";k=0}

/ProcessName/,/^$/   {a[k++]=$0; 
                     if(match($0,"error")!= 0) {flag="yes"};
                     }

/^$/                 {if (flag=="yes") {flag="no"; 
                                       for ( i=0; i<k; i++ ){print a[i]}
                                       print "-------";
                                      }; 
                     for ( r in a ){delete a[r]};k=0;
                     }

Test:

Input:

ProcessName
adasd
asdasd

ProcessName with err 
error  
salutti

ProcessName no err  
aaa
no err 

ProcessName  

Output:

ProcessName with err 
error  
salutti

-------

Running at ideone here

Edit

On your comment about having sometimes an empty record before the error record, you can solve that by pre-processing your log files with the following awk script that deletes the empty lines before the error messages:

/^$/ {getline; if($0 !~ /error/) print ""}  
{print}  

and then running the main script on the output of this one.


Give this a try

awk '/ProcessName/{a = $0; next} {a = a RS $0} /error:/{print a}' inputfile

It accumulates lines and resets the accumulator each time it sees "ProcessName". When it sees "error:" it prints the contents of the accumulator.


Next time, show some sample input

awk 'BEGIN{RS=""}/ProcessName/ && /Error/' file


$ cat file
ProcessName
adasd
asdasd

ProcessName with err
error
salutti

ProcessName no err
aaa
no err

$ awk 'BEGIN{RS=""}/ProcessName/ && /err/' file
ProcessName with err
error
salutti
ProcessName no err
aaa
no err


for blank-line delimited files, I find Perl easiest:

perl -00 -ne 'print if /^ProcessName/ && /error/' afile

The -00 option is the magic incantation to pass the file a paragraph at a time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜