【问题标题】:average columns based on one column基于一列的平均列
【发布时间】:2015-02-23 21:12:23
【问题描述】:

这是运行一段时间的示例 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

我需要适用于任意数量的列和磁盘名称的东西。

【问题讨论】:

  • @EdMorton 进行了更改

标签: bash awk sed


【解决方案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 &gt; 2。我不确定这是否应该是您输入的一部分)。

【讨论】:

    【解决方案2】:

    获取数据的方法如下:

    $ 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 或其他任何方式格式化输出时遇到问题,请告诉我们...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      相关资源
      最近更新 更多