Awk 如何处理匹配模式之间的字段?
相关职位: @fedorqui,感谢您为awk提供所有这些不同的选项。在对oom进行故障排除时,我一直在使用它来解析var日志消息,效果非常好。我想进一步扩展,但我还没有弄清楚如何继续。我想做的是:Awk 如何处理匹配模式之间的字段?,awk,Awk,相关职位: @fedorqui,感谢您为awk提供所有这些不同的选项。在对oom进行故障排除时,我一直在使用它来解析var日志消息,效果非常好。我想进一步扩展,但我还没有弄清楚如何继续。我想做的是: 打印rss和内存不足之间的行。我已经用这个例子做到了 按rss字段对每个匹配项之间的节进行排序。我一直没能弄明白这一点 添加一个具有自己标题的额外列,并执行一些数学运算。我已经能够做到这一点,但我遇到了一些格式问题。我不知道在添加列时如何跳过第一行和最后一行,因此我丢失了这些行。如果我进行打印以外的
less /var/log/messages'|awk '/swapents/{x=1; print "=================="};/Out of memory/{x=0} x'|sed 's/[]\[]//g'
以下是源数据:
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.617265 pid uid tgid total_vm rss nr_ptes nr_pmds swapents oom_score_adj name
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.622250 1828 0 1828 4331 116 14 3 0 -1000 udevd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.627310 2664 0 2664 28002 53 23 3 0 -1000 auditd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.633181 2680 0 2680 62032 1181 24 4 0 0 rsyslogd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.638888 2694 0 2694 3444 61 11 3 0 0 irqbalance
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.644912 2710 81 2710 5430 56 14 3 0 0 dbus-daemon
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.651108 2779 0 2779 19958 203 42 3 0 -1000 sshd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.656670 2789 0 2789 5622 56 17 3 0 0 xinetd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.653452 Out of memory: Kill process 43390 (mysql) score 1000 or sacrifice child
blah
blah
blah
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.617265 pid uid tgid total_vm rss nr_ptes nr_pmds swapents oom_score_adj name
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.622250 1828 0 1828 4331 116 14 3 0 -1000 udevd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.627310 2664 0 2664 28002 53 23 3 0 -1000 auditd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.633181 2680 0 2680 62032 1181 24 4 0 0 rsyslogd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.638888 2694 0 2694 3444 61 11 3 0 0 irqbalance
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.644912 2710 81 2710 5430 56 14 3 0 0 dbus-daemon
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.651108 2779 0 2779 19958 203 42 3 0 -1000 sshd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.656670 2789 0 2789 5622 56 17 3 0 0 xinetd
Sep 8 11:35:15 ip-10-23-15-70 kernel: 11810061.653452 Out of memory: Kill process 43390 (mysql) score 1000 or sacrifice child
我的输出如下所示:
================== 0MB
Sep 8 11:35:15 pid 0MB name <---- should be header (Pid virt rss etc)
Sep 8 11:35:15 1828 0MB udevd
Sep 8 11:35:15 2664 0MB auditd
Sep 8 11:35:15 2680 4MB rsyslogd
Sep 8 11:35:15 2694 0MB irqbalance
Sep 8 11:35:15 2710 0MB dbus-daemon
Sep 8 11:35:15 2779 0MB sshd
Sep 8 11:35:15 2789 0MB xinetd
Sep 8 11:35:15 2822 0MB crond
Sep 8 11:35:15 Out 0MB or <---- should be footer (out of memory etc)
================== 0MB
Sep 8 11:35:15 pid 0MB name <---- should be header (Pid virt rss etc)
Sep 8 11:35:15 1828 0MB udevd
Sep 8 11:35:15 2664 0MB auditd
Sep 8 11:35:15 2680 4MB rsyslogd
Sep 8 11:35:15 2694 0MB irqbalance
Sep 8 11:35:15 2710 0MB dbus-daemon
Sep 8 11:35:15 2779 0MB sshd
Sep 8 11:35:15 2789 0MB xinetd
Sep 8 11:35:15 2822 0MB crond
Sep 8 11:35:15 Out 0MB or <---- should be footer (out of memory etc)
================== 0MB
awk解决方案:
$ cat tst.awk
/swapents/ {
x=1;
print "=================="
printf( "%s %s %s pid\t%4s\tmemused_MB\toom_score_adj\tname\n", $1, $2, $3, "rss");
next
}
/Out of memory/ {
printf( "%s %s %s %s\n", $1, $2, $3, substr($0,index($0,$7)));
x=0
}
x {
printf( "%s %s %s %s\t%4d\t%10.5f\t%13d\t%s\n", $1, $2, $3, $7, $11, ($11*4)/1024, $15, $16 )
}
您可以使用printf函数中的说明符处理格式,如第6列中的精度。请使用以下命令调用此命令:
$ awk -f tst.awk /var/log/messages
编辑:带排序
OP要求按rss列对输出进行排序。使用标准的排序
在这里不起作用,因为您希望在开始和结束匹配之间进行排序。您可以通过将中间结果保存在数组中并使用自定义函数对其进行排序来解决此问题。像这样:
$ cat tst2.awk
/swapents/ {
x=1;
print "=================="
printf( "%s %s %s pid\t%4s\tmemused_MB\toom_score_adj\tname\n", $1, $2, $3, "rss");
next
}
/Out of memory/ {
n=asort(a, sorted, "cmp_rss")
for (i=1; i<=n; i++) {
print sorted[i]
}
delete a;
printf( "%s %s %s %s\n", $1, $2, $3, substr($0,index($0,$7)));
x=0
}
x {
a[i++] = sprintf( "%s %s %s %s\t%4d\t%10.5f\t%13d\t%s", $1, $2, $3, $7, $11, ($11*4)/1024, $15, $16 );
}
function cmp_rss(i1, v1, i2, v2)
{
split(v1, a1, " ")
split(v2, a2, " ")
rss1=a1[5];
rss2=a2[5];
return (rss1 - rss2)
}
根据Marc Lambrich的回答,我能够创建一个行程序来完成这项工作。非常感谢。现在唯一缺少的是按rss列进行排序,但我无法对rss字段进行排序
less /var/log/messages|awk '/swapents/ {x=1; print "==================";gsub(/\[|\]/, "") ;printf "%s %s %s %s %10s %10s %10s %15s memory_used %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$16 ;next } {gsub(/\[|\]/, "")} /Out of memory/ {print $0 ;x=0 } x {printf "%s %s %s %s %10s %10s %10s %15s %9.2fMB %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$11*4/1024,$16}'
为便于阅读,awk代码的格式为:
/swapents/ {
x=1;
print "==================";
gsub(/\[|\]/, "");
printf "%s %s %s %s %10s %10s %10s %15s memory_used %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$16 ;
next
}
{
gsub(/\[|\]/, "")
}
/Out of memory/ {
print $0;
x=0
}
x {
printf "%s %s %s %s %10s %10s %10s %15s %9.2fMB %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$11*4/1024,$16
}
嘿,很棒的解决方案。这是我用过的/swappents/{x=1;print“===================“gsub(/[|]/,”“)print$0”\t\t“$11 next}{gsub(/[|]/,”“)}/内存不足/{print$0 x=0}x{printf”%s\t\t%10.2f\n“,$0,$11*4/1024}这并不排序。有没有一种方法可以在命令行中使用它而不创建文件?我无法在我使用的计算机上创建文件。添加了rss列的排序示例。不创建文件?当然,只是
awk-f tst2.awk input.txt
不会为您创建文件。谢谢您的排序方法,这很酷。通过不创建文件,我的意思是我无法在运行此操作的机器上创建awk文件。看起来我可能需要从外部进行排序:(.谢谢你的帮助,现在就可以了,不用排序就可以生存。我可以想象你不被允许访问公司的生产服务器。但是,有些公司在允许读取访问的地方使用日志服务器。还有:没有义务,但是如果你真的满意的话,你可以接受答案。是的,这是真的,但是日志服务器只有e记录了2天前的日志。所以我不得不等待,因为问题现在正在发生,所以我不得不等待。在我的答案中添加了排序示例。
less /var/log/messages|awk '/swapents/ {x=1; print "==================";gsub(/\[|\]/, "") ;printf "%s %s %s %s %10s %10s %10s %15s memory_used %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$16 ;next } {gsub(/\[|\]/, "")} /Out of memory/ {print $0 ;x=0 } x {printf "%s %s %s %s %10s %10s %10s %15s %9.2fMB %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$11*4/1024,$16}'
/swapents/ {
x=1;
print "==================";
gsub(/\[|\]/, "");
printf "%s %s %s %s %10s %10s %10s %15s memory_used %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$16 ;
next
}
{
gsub(/\[|\]/, "")
}
/Out of memory/ {
print $0;
x=0
}
x {
printf "%s %s %s %s %10s %10s %10s %15s %9.2fMB %-s\n", $1,$2,$3,$4,$7,$10,$11,$15,$11*4/1024,$16
}