如何处理匹配模式之间的字段?

时间:2017-09-10 16:57:16

标签: awk

相关文章:How to select lines between two patterns?

@fedorqui,感谢为awk提供所有这些不同的选项。在对ooms进行故障排除时,我一直在使用它来解析var日志消息,它运行良好。我想进一步扩展这一点但我无法弄清楚如何继续。我想做什么:

  1. 打印rss和内存不足之间的行。我已经通过示例

  2. 完成了这项工作
  3. 通过rss字段对每个匹配项之间的部分进行排序。我无法弄明白

  4. 添加一个带有自己标题的额外列,并执行一些数学运算。我已经能够做到这一点,但我遇到了一些格式问题。我不知道在添加列时如何跳过第一行和最后一行,所以我丢失了这些行。如果我进行除打印之外的任何操作,我也无法保持与原件的间距。

  5. 这是我现在使用的命令:

    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
    

    你可以从输出中看到我为每个oom字段添加的分隔符,awk尝试计算它的值,我希望尽可能避免这种情况。页眉和页脚也被砍掉了,也可以避免这样做。

    这就是我想要的:

    ========================
    Sep  8 11:35:15   pid   rss  memused_MB      oom_score_adj name
    Sep  8 11:35:15   2664   53  {rss*4/1024}            -1000 auditd
    Sep  8 11:35:15   2789   56  {rss*4/1024}                0 xinetd 
    Sep  8 11:35:15   2710   56  {rss*4/1024}                0 dbus-dae
    Sep  8 11:35:15   2694   61  {rss*4/1024}                0 irqbalan
    Sep  8 11:35:15   1828  116  {rss*4/1024}            -1000 udevd 
    Sep  8 11:35:15   2680  181  {rss*4/1024}                0 rsyslogd 
    Sep  8 11:35:15   2779  203  {rss*4/1024}            -1000 sshd 
    Sep  8 11:35:15   Out of memory: Kill process 43390 (mysql) score 1000 or sacrifice child
    ========================
    Sep  8 11:35:15   pid   rss  memused_MB      oom_score_adj name
    Sep  8 11:35:15   2664   53  {rss*4/1024}            -1000 auditd
    Sep  8 11:35:15   2789   56  {rss*4/1024}                0 xinetd 
    Sep  8 11:35:15   2710   56  {rss*4/1024}                0 dbus-dae
    Sep  8 11:35:15   2694   61  {rss*4/1024}                0 irqbalan
    Sep  8 11:35:15   1828  116  {rss*4/1024}            -1000 udevd 
    Sep  8 11:35:15   2680  181  {rss*4/1024}                0 rsyslogd 
    Sep  8 11:35:15   2779  203  {rss*4/1024}            -1000 sshd 
    Sep  8 11:35:15   Out of memory: Kill process 43390 (mysql) score 1000 or sacrifice child
    ========================  
    

2 个答案:

答案 0 :(得分:1)

awk 解决方案:

$ echo 4.0 >.swift-version

您可以使用printf函数中的说明符来处理格式化,例如第6列中的精度。请拨打以下电话:

$ 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 )
}
  

编辑:排序

OP要求按rss列对输出进行排序。使用标准$ awk -f tst.awk /var/log/messages 在这里不起作用,因为您想要在开始和结束匹配之间进行排序。您可以通过将中间结果保存在数组中并使用自定义函数对其进行排序来解决此问题。像这样:

sort

导致:

$ 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)
} 

答案 1 :(得分:0)

根据Marc Lambrichs的回应,我能够创建这个完成工作的一个班轮。非常感谢。现在唯一缺少的是按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
}