使用awk解析日志行

时间:2012-04-06 18:46:35

标签: parsing sed awk logging

我必须从大日志文件行中解析一些信息。 它的类似

abc.log:2012-03-03 11:12:12,457 ABC[123.RPH.-101] XYZ: Query=get_data @a=0,@b=1 Rows=10Time=100   

日志文件中有如上所示的许多日志行。我需要提取信息           datetime ie 2012-03-03 11:12:12,457        工作细节,即123.RPH.-101       查询即get_data(无参数)      行数即10      时间即100

因此输出应该看起来像

2012-03-03 11:12:12,457|123|-101|get_data|10|100  

我已尝试使用awk进行各种排列计算但未正确使用。

5 个答案:

答案 0 :(得分:1)

嗯,这真的太可怕了,但是因为sed在标签中并且还没有答案......

sed -e 's/[^0-9]*//' -re 's/[^ ]*\[([^.]*)\.[^.]*\.([^]]*)\]/| \1 | \2/' -e 's/[^ ]* Query=/| /' -e 's/ [^ ]* Rows=/ | /' -e 's/Time=/ | /' my_logfile

答案 1 :(得分:1)

TXR:

@(collect :vars ())
@file:@year-@mon-@day @hh:@mm:@ss,@ms @jobname[@job1.RPH.@job2] @queryname: Query=@query @params Rows=@{rows /[0-9]+/}Time=@time
@(output)
@year-@mon-@day @hh-@mm-@ss,@ms|@job1|@job2|@query|@rows|@time
@(end)
@(end)

执行命令

$ txr data.txr data.log
2012-03-03 11-12-12,457|123|-101|get_data|10|100

这是使程序断言日志文件中的每一行必须与模式匹配的一种方法。首先,不要在集合中留有空白。这意味着不能跳过不匹配的材料来查找匹配的行:

@(collect :gap 0 :vars ())

其次,在脚本的最后我们添加:

@(eof)

指定文件末尾的匹配项。如果@(collect)由于不匹配的行(由于:gap 0约束)而导致提前失败,则@(eof)将失败,因此脚本将以失败状态终止。

在这种类型的任务中,字段拆分正则表达式攻击会适得其反,因为它们可能会盲目地为正在处理的输入的某个子集产生不正确的结果。如果输入包含大量行,则没有简单的方法来检查错误。最好有一个非常具体的匹配,可能会拒绝任何与模式所基于的示例不相似的东西。

答案 2 :(得分:1)

我在gawk中的解决方案:它使用gawk扩展来匹配。

您没有指定文件格式,因此您可能需要调整正则表达式。

脚本调用: gawk -v OFS='|' -f script.awk

{
match($0, /[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+,[0-9]+/)
date_time = substr($0, RSTART, RLENGTH)

match($0, /\[([0-9]+).RPH.(-?[0-9]+)\]/, matches)
job_detail_1 = matches[1]
job_detail_2 = matches[2]

match($0, /Query=(\w+)/, matches)
query = matches[1]

match($0, /Rows=([0-9]+)/, matches)
rows = matches[1]

match($0, /Time=([0-9]+)/, matches)
time = matches[1]

print date_time, job_detail_1, job_detail_2, query,rows, time
}

答案 3 :(得分:1)

这是另一种不那么花哨的AWK解决方案(但也适用于mawk):

BEGIN { OFS="|" }

{
    i = match($3, /\[[^]]+\]/)
    job = substr($3, i + 1, RLENGTH - 2)
    split($5, X, "=")
    query = X[2]
    split($7, X, "=")
    rows = X[2]
    split($8, X, "=")
    time= X[2]

    print $1 " " $2, job, query, rows, time
}

请注意,这假设Rows=10Time=100字符串由空格分隔,即问题示例中存在拼写错误。

答案 4 :(得分:0)

只需要正确的字段分隔符

awk -F '[][ =.]' -v OFS='|' '{print $1 " " $2, $4, $6, $10, $15, $17}'

我假设“abc.log:”实际上并不在日志文件中。