基于一列的平均列

时间:2015-02-23 21:12:23

标签: bash awk sed

这是运行一段时间的示例IOstat数据。(我删除了空行,空格等) 我需要每个磁盘的每列的平均值。

知道怎么用awk / sed吗?

  125.7   39.9  979.3  394.4  0.0  2.2    0.1 13.462   0  27 c1t5000CCA01BBC5A7Cd0
  127.1   39.8  977.6  394.5  0.0  2.2    0.0 13.441   0  27 c1t5000CCA01BBC59ACd0
  126.7   39.9  975.8  394.0  0.0  2.2    0.1 12.926   0  26 c1t5000CCA01BBC59DCd0
  126.2   40.0  970.5  394.0  0.0  2.2    0.0 13.115   0  26 c1t5000CCA01BBC5A2Cd0
    7.9    0.0   10.9    0.0  0.0  0.0    0.0  0.152   0   0 c3t0d0
  124.7  183.0 1236.0 2075.1  0.0  7.6    0.0 24.838   0  35 c1t5000CCA01BBC5A2Cd0
    0.0  148.4    0.0  322.4  0.0  6.6    0.0 44.482   0  38 c3t0d0
   32.0    9.7  178.1    3.9  0.0  0.3    0.0  7.822   0  15 c1t5000CCA01BBC5980d0
   62.1    0.0   31.0    0.0  0.0  0.0    0.0  0.000   0   0 c1t5000CCA01BBC5950d0
   37.8    9.7  346.8    3.9  0.0  0.3    0.0  6.821   0  15 c1t5000CCA01BBC5A44d0
   54.3    4.8  649.4    0.0  0.0  1.6    0.0 27.885   0  19 c1t5000CCA01BBC58E4d0
   50.4    9.7  622.2    3.9  0.0  0.7    0.0 11.007   0  19 c1t5000CCA01BBC5A48d0
   90.2    4.8 1922.2    0.0  0.0  2.8    0.0 29.611   0  25 c1t5000CCA01BBC5AA8d0
   62.1  161.0   31.0  354.4  0.0  0.8    0.0  3.777   0   5 c1t5000CCA01BBC5918d0
  102.8  430.6 1897.1 26280.3  0.0  1.7    0.0  3.281   0  11 c1t5000CCA01324687Cd0
  496.5 20587.8 1988.1 96156.7  0.1 13.4    0.0  0.637   6  46 c1t5000CCA0132475ACd0
  487.8 20588.8 1961.0 96160.6  0.1 13.5    0.0  0.640   6  46 c1t5000CCA0132477ECd0

编辑:

输入文件

c1 c2 c3 c4 diskname

1  1   1 1   d1
1  2   3 2   d2
2  1   4 3   d3
3  2   3 2   d1
1  2   3 2   d2
1  2   3 2   d3

预期产出

Avg_c1 Avg_c2 Avg_c3 Avg_c4    diskname
  2     1.5     2      1.5    d1
  1      2      3       2     d2
 1.5    1.5    3.5     2.5    d3

其中

 X={d1,d2,d3}
 Y={c1,c2,c3,c4}

Avg_[Y] for X = sum of column Y where diskname is X/number of entries of X

我需要适用于任意数量的列和磁盘名的内容。

2 个答案:

答案 0 :(得分:1)

使用awk:

awk '{ fields[$NF] = NF; ++ctr[$NF]; for(i = 1; i < NF; ++i) { sum[$NF,i] += $i } } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for(c in ctr) { for(i = 1; i < fields[c]; ++i) { printf("%.3f\t", sum[c,i] / ctr[c]) } print c } }' filename

那是:

{
  ++ctr[$NF]                   # in every line, count how often the disk
  for(i = 1; i < NF; ++i) {    # appeared and sum up the fields
    sum[$NF,i] += $i
  }
}
END {                          # in the end, print the tallies
                               # divided by the counter (the averages)

  # PROCINFO["sorted_in"] is GNU-specific, for sorted traversal. If that is a
  # problem or not necessary, it is safe to remove it.
  PROCINFO["sorted_in"] = "@ind_str_asc"

  for(c in ctr) {
    for(i = 1; i < NF; ++i) { 
      printf("%.3f\t", sum[c,i] / ctr[c])
    }
    print c
  }
}

要跳过标题行,请输入

NR > 1

在第一个{之前(要跳过两个,请使用NR > 2。我不确定这是否应该是您输入的一部分。)

答案 1 :(得分:1)

以下是获取数据的方法:

$ cat tst.awk        
NR==1 {
   key = $NF
   $NF = ""
   gsub(/[^[:space:]]+/,"Avg_&")
   print $0 key
   next
}
NF {
   for (i=1;i<NF;i++) {
       sum[$NF,i] += $i
   }
   cnt[$NF]++
}
END {
   for (key in cnt) {
       for (i=1;i<NF;i++) {
           printf "%s%s", sum[key,i] / cnt[key], OFS
       }
       print key
   }
} 
$ awk -f tst.awk file
Avg_c1 Avg_c2 Avg_c3 Avg_c4 diskname
2 1.5 2 1.5 d1
1 2 3 2 d2
1.5 1.5 3.5 2.5 d3

如果您在使用printf格式化输出或管道输入column或其他任何内容时,请告诉我们。