【问题标题】:Awk command print max min values from logawk 命令从日志中打印最大最小值
【发布时间】:2014-11-20 07:16:47
【问题描述】:

我正在使用成功标志 S 执行grep。$11 是服务类型,$12 是 S(成功)或 F(失败),$14 是经过的时间。下面的命令我得到平均经过的时间。

bash-3.2$ grep 'EXSTAT|' ivrbroker.log | grep '|F|' |
> /usr/xpg4/bin/awk -F"|" '{a[$11]++;c[$11]+=$14}
>    END{for(b in a){print b"," a[b]","c[b]/a[b]}}'
QCPE,2,276.5
bash-3.2$ grep 'EXSTAT|' ivrbroker.log|grep '|F|'       
EXSTAT|IVR|2014|11|17|14|43|57|1086|SRQCPE952|QCPE|F|100|349
EXSTAT|IVR|2014|11|17|15|35|51|1092|SRQCPE741|QCPE|F|100|204

但现在我正在寻找最大经过时间和最小经过时间,如下所示。

QCPE,2,276.5,349,204

bash-3.2$ grep '|F|' ivrbroker.log
EXSTAT|IVR|2014|11|17|14|43|57|1086|SRQCPE952|QCPE|F|100|349
EXSTAT|IVR|2014|11|17|15|35|51|1092|SRQCPE741|QCPE|F|100|204
bash-3.2$ awk -F'|' 'BEGIN { OFS="," }
    /EXSTAT\|/ && /\|F\|/ { a[$11]++; c[$11] += $14;
        if (a[$11]==1) { max[$11]=$14; min[$11]=$14; }
        if($14 > max[$11]) max[$11]=$14;  if($14 < min[$11]) min[$11]=$14; }
    END { for(b in a) print b, a[b], c[b]/a[b], max[b], min[b] }' ivrbroker.log
,204,2,0,349
bash-3.2$ /usr/xpg4/bin/awk -F'|' 'BEGIN { OFS="," }                                                                                                                                                     
    /EXSTAT\|/ && /\|F\|/ { a[$11]++; c[$11] += $14;
       if (a[$11]==1) { max[$11]=$14; min[$11]=$14; }
       if($14 > max[$11]) max[$11]=$14;  if($14 < min[$11]) min[$11]=$14; }
    END { for(b in a) print b, a[b], c[b]/a[b], max[b], min[b] }' ivrbroker.log
,204,2,276.5,349
bash-3.2$ 

【问题讨论】:

  • /usr/xpg4/bin/awk 路径看起来你根本不在 Linux 上。标签linux 不正确吗?如果是这样,您在哪个平台上?
  • bash-3.2$ uname -a SunOS utibcouat1 5.10 Generic_150400-13 sun4u sparc SUNW,Sun-Fire-V440 操作系统是 sun solaris 5.10。
  • 我无法在 Linux 上轻松访问 sawk。如果您可以切换到gawk,我相信这应该可以解决任何剩余的兼容性问题。
  • 更新答案时出现语法错误。我已经编辑并发布了输出以供参考。
  • 不幸的是,我无法访问 SysV awk 进行测试。该脚本在mawknawkgawk 上运行良好。问题似乎与!($11 in max) 表达式有关——我试图设计一个解决方法,但我不知道它是否会起作用。我再次更新了我的答案。

标签: shell awk solaris sunos


【解决方案1】:

您需要再添加两个数组变量来跟踪最小值和最大值。

当您使用它时,请摆脱 grep | awk 反模式。

awk -F'|' 'BEGIN { OFS="," }
    /EXSTAT\|/ && /\|F\|/ { a[$11]++; c[$11] += $14;
        if (!($11 in max)) max[$11]=min[$11]=$14;
        if($14 > max[$11]) max[$11]=$14;  if($14 < min[$11]) min[$11]=$14; }
    END { for(b in a) print b, a[b], c[b]/a[b], max[b], min[b] }' ivrbroker.log

看起来第一个条件应该是$1 == "EXSTAT" &amp;&amp; $12 == "F",以稍微提高易读性和精确度。也许还可以将 a 重命名为 countc 重命名为 sum

上面的脚本可以在 Linux 上运行,但显然不能在 SunOS / SysV / XPG4 Awk 上运行。也许试试这个小修改:

awk -F'|' 'BEGIN { OFS="," }
    /EXSTAT\|/ && /\|F\|/ { a[$11]++; c[$11] += $14;
        if (a[$11]==1) { max[$11]=$14; min[$11]=$14; }
        if($14 > max[$11]) max[$11]=$14;  if($14 < min[$11]) min[$11]=$14; }
    END { for(b in a) print b, a[b], c[b]/a[b], max[b], min[b] }' ivrbroker.log

【讨论】:

  • 我同时更新了答案。我的原始答案适用于您发布的示例数据(2 行);如果示例不具有代表性,请更新。
  • 您的答案是完全可移植的,适用于所有现代 awk。如果 OP 遇到语法错误,那么要么他没有正确复制/粘贴它,要么他试图在其上运行旧的、损坏的 awk(Solaris 上的 /bin/awk)。
猜你喜欢
  • 2018-09-05
  • 1970-01-01
  • 2022-11-16
  • 2019-05-26
  • 2015-02-20
  • 2017-08-07
  • 2014-04-04
  • 1970-01-01
  • 2017-10-10
相关资源
最近更新 更多