【问题标题】:How to perform calculation over a log file如何对日志文件执行计算
【发布时间】:2010-10-11 09:43:48
【问题描述】:

我有一个看起来像这样的:

I, [2009-03-04T15:03:25.502546 #17925]  INFO -- : [8541, 931, 0, 0]
I, [2009-03-04T15:03:26.094855 #17925]  INFO -- : [8545, 6678, 0, 0]
I, [2009-03-04T15:03:26.353079 #17925]  INFO -- : [5448, 1598, 185, 0]
I, [2009-03-04T15:03:26.360148 #17925]  INFO -- : [8555, 1747, 0, 0]
I, [2009-03-04T15:03:26.367523 #17925]  INFO -- : [7630, 278, 0, 0]
I, [2009-03-04T15:03:26.375845 #17925]  INFO -- : [7640, 286, 0, 0]
I, [2009-03-04T15:03:26.562425 #17925]  INFO -- : [5721, 896, 0, 0]
I, [2009-03-04T15:03:30.951336 #17925]  INFO -- : [8551, 4752, 1587, 1]
I, [2009-03-04T15:03:30.960007 #17925]  INFO -- : [5709, 5295, 0, 0]
I, [2009-03-04T15:03:30.966612 #17925]  INFO -- : [7252, 4928, 0, 0]
I, [2009-03-04T15:03:30.974251 #17925]  INFO -- : [8561, 4883, 1, 0]
I, [2009-03-04T15:03:31.230426 #17925]  INFO -- : [8563, 3866, 250, 0]
I, [2009-03-04T15:03:31.236830 #17925]  INFO -- : [8567, 4122, 0, 0]
I, [2009-03-04T15:03:32.056901 #17925]  INFO -- : [5696, 5902, 526, 1]
I, [2009-03-04T15:03:32.086004 #17925]  INFO -- : [5805, 793, 0, 0]
I, [2009-03-04T15:03:32.110039 #17925]  INFO -- : [5786, 818, 0, 0]
I, [2009-03-04T15:03:32.131433 #17925]  INFO -- : [5777, 840, 0, 0]

我想创建一个 shell 脚本来计算括号中的第二个和第三个字段的平均值(最后一个示例中的 8400)。一个更棘手的问题:是否只有当最后一个不是0时才能得到第三个字段的平均值?

我知道我可以使用Ruby 或其他语言来创建脚本,但我想在Bash 中进行。有关如何创建此类脚本的资源或提示的任何好的建议都会有所帮助。

【问题讨论】:

  • 在 awk 中执行此操作很简单。这算作“用 bash 做”吗?

标签: parsing shell awk gawk


【解决方案1】:

使用bashawk

cat file | sed -ne 's:^.*INFO.*\[\([0-9, ]*\)\][ \r]*$:\1:p' | awk -F ' *, *' '{ sum2 += $2 ; sum3 += $3 } END { if (NR>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/NR, sum3/NR }'

示例输出(用于您的原始数据):

avg2=2859.59, avg3=149.94

当然,您不需要使用cat,它包含在其中是为了便于阅读并说明输入数据可以来自任何管道的事实;如果必须对现有文件进行操作,请直接运行sed -ne '...' file | ...


编辑

如果您有权访问 gawk (GNU awk),则可以消除对 sed 的需要,如下所示:

cat file | gawk '{ if(match($0, /.*INFO.*\[([0-9, ]*)\][ \r]*$/, a)) { cnt++; split(a[1], b, / *, */); sum2+=b[2]; sum3+=b[3] } } END { if (cnt>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/cnt, sum3/cnt }'

同样的评论。 cat申请。

一点解释:

  • sed 仅打印出与正则表达式匹配的行(-n ... :p 组合)(包含 INFO 的行后跟在行尾的方括号之间的数字、空格和逗号的任意组合,允许尾随空格和 CR);如果任何这样的行匹配,只保留方括号之间的内容(\1,对应于正则表达式中\(...\)之间的内容),然后再打印(:p
    • sed 将输出如下所示的行:8541, 931, 0, 0
  • awk 使用由 0 个或多个空格 (-F ' *, *') 包围的逗号作为字段分隔符; $1 对应于第一列(例如 8541),$2 对应于第二列等等。缺失的列算作值 0
    • 最后,awk 将累加器 sum2 等除以处理的记录数,NR
  • gawk 一次完成所有事情;它将首先测试每一行是否匹配上一个示例中传递给sed 的相同正则表达式(除了与sed 不同,awk 不需要在圆括号分隔区域或兴趣的前面使用\)。如果该行匹配,则圆括号之间的内容以 a[1] 结尾,然后我们使用相同的分隔符(由任意数量的空格包围的逗号)将其拆分并使用它来累加。我介绍了cnt,而不是继续使用NR,因为如果不是所有行都采用INFO ... [...comma-separated-numbers...] 的形式,处理的记录数NR 可能大于相关记录的实际数量(cnt),即sed|awk 的情况并非如此,因为 sed 保证传递给 awk 的所有行都是相关的。

【讨论】:

  • 太棒了!也感谢您的解释!
【解决方案2】:

在这里也发布我通过 IM 粘贴给你的回复,只是因为它让我尝试 StackOverflow :)

# replace $2 with the column you want to avg; 
awk '{ print $2 }' | perl -ne 'END{ printf "%.2f\n", $total/$n }; chomp; $total+= $_; $n++' < log

【讨论】:

    【解决方案3】:

    Solaris 上使用 nawk/usr/xpg4/bin/awk

    awk -F'[],]' 'END { 
      print s/NR, t/ct 
      }  
    { 
      s += $(NF-3) 
      if ($(NF-1)) {
        t += $(NF-2)
        ct++
        }
      }' infile
    

    【讨论】:

      【解决方案4】:

      使用 Python

      logfile= open( "somelogfile.log", "r" )
      sum2, count2= 0, 0
      sum3, count3= 0, 0
      for line in logfile:
          # find right-most brackets
          _, bracket, fieldtext = line.rpartition('[')
          datatext, bracket, _ = fieldtext.partition(']')
          # split fields and convert to integers
          data = map( int, datatext.split(',') )
          # compute sums and counts
          sum2 += data[1]
          count2 += 1
          if data[3] != 0:
              sum3 += data[2]
              count3 += 1
      logfile.close()
      
      print sum2, count2, float(sum2)/count2
      print sum3, count3, float(sum3)/count3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-09
        • 1970-01-01
        • 2021-09-22
        • 2016-12-11
        • 1970-01-01
        • 2012-08-16
        • 1970-01-01
        相关资源
        最近更新 更多