Reputation: 385
This is sample IOstat data running for a period of time.(I have removed empty lines,spaces etc) I need the average of each column for each disk.
Any idea how to do it using 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
EDIT:
Input file
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
Expected Output
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
Where
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
I need something that works for any number of columns and disknames.
Upvotes: 0
Views: 68
Reputation: 203169
Here's how to get the data:
$ 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
Let us know if you have trouble formatting the output using printf
or piping to column
or whatever...
Upvotes: 1
Reputation: 44023
With 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
That is:
{
++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
}
}
To skip a header line, put
NR > 1
before the first {
(to skip two, use NR > 2
. I'm not sure if that's supposed to be part of your input).
Upvotes: 1