试图用 awk 从我的日志中隔离一个块,请帮忙!

发布于 2024-10-18 06:10:31 字数 1139 浏览 2 评论 0原文

我正在尝试编写一个 awk 脚本,该脚本可以从长日志文件中获取包含单词“错误”的块。

基本上这个日志文件包含执行的操作,当其中一个操作失败时,它会在该操作下添加错误行,说明出了什么问题。

我可以轻松地隔离错误行,只需对“error:”执行 grep,但我缺少给出的命令,因为它是在错误行之前打印的,而且我不知道之前有多少行,所以不能随意说“print “error:”一词之前的 10 行

我已经想出了一种方案;每个可能包含错误行的块都以相同的方式开始(“ProcessName”),后面跟着命令和其他参数,每个都在不同的行上,最后一行将始终是一个空行

所以我的想法是使用 awk 来使用这个块,这样我就可以查找“processName”字符串,开始逐行打印直到。我到达空行,然后通过 grep 管道打印结果以查看其中是否有“错误:”一词,如果有错误,那么我将重定向到文件并附加整个块,否则它将继续到下一个块并做同样的事情,

如果我能帮助完成这项任务,那真的会有帮助,因为我真的不知道如何才能实现这一目标;我刚刚查看了 awk,它似乎是完成这项工作的正确工具(我可以为该任务编写一个 shell 脚本),但如果您认为有更好的方法在 shell 脚本中完成它,我是洗耳恭听:)

预先感谢您的帮助!

更新:感谢您的脚本;我已经从丹尼斯得到了一个可以工作的,但是如果每个块中有多个错误条目,它会多次打印同一个块;而贝利撒留的示例不返回任何行。

当我引入错误时,我添加了一个我的日志的示例(末尾有一个空行,但如果我将文本放入标签代码中则无法添加它):

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

常规块看起来完全相同,但显然没有错误:部分。

希望这能让我更清楚,再次感谢!

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 regular block looks exactly the same, but does not have the error: part obviously.

Hope that this makes it more clear, thanks again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遗失的美好 2024-10-25 06:10:31

您可以尝试:

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;
                     }

测试:

输入:

ProcessName
adasd
asdasd

ProcessName with err 
error  
salutti

ProcessName no err  
aaa
no err 

ProcessName  

输出:

ProcessName with err 
error  
salutti

-------

在此处运行 ideone

编辑

关于您关于错误记录之前有时有一个空记录的评论,您可以通过使用以下 awk 脚本预处理日志文件来解决该问题,该脚本会删除错误记录之前的空行错误消息:

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

然后在该输出上运行主脚本。

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.

守不住的情 2024-10-25 06:10:31

尝试一下

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

它会累积行并在每次看到“ProcessName”时重置累加器。当它看到“错误:”时,它会打印累加器的内容。

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.

寻梦旅人 2024-10-25 06:10:31

下次,展示一些示例输入

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

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
烟酉 2024-10-25 06:10:31

对于空行分隔的文件,我发现 Perl 最简单:

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

-00 选项是一次传递文件一段的魔法。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文