-2

我在 linux 服务器上有一个文件,其中包含以下数据:

a   22
a   10
a   17
a   51
a   33
b   51
b   47
c   33

我想要一个 shell 脚本或 linux 命令来查找第 1 列中每个值的最小值、平均值、90%、最大值和计数。

例子:

for a min = 10, avg = 26, 90% = 33, max = 51, and count = 5.
4

3 回答 3

0

对于以 开头的行a,这里有一个awk脚本。

$ echo 'a 22
a 10
a 17
a 51
a 33
b 51
b 47
c 33' | awk 'BEGIN{n=0;s=0;};/^a/{n=n+1;s=s+$2;};END{print n;print s;print s/n;}'
5
133
26.6
于 2013-08-27T10:24:09.047 回答
0

使用 awk:

awk 'NR==1{min=$1} {sum+=$2; if(min>=$2) min=$2; if(max<$2) max=$2} 
     END{printf("max=%d,min=%d,count=%d,avg=%.2f\n", max, min, NR, (sum/NR))}' file
max=51,min=10,count=8,avg=33.00

编辑:

awk '$1 != v {
   if (NR>1)
      printf("For %s max=%d,min=%d,count=%d,avg=%.2f\n", v, max, min, k, (sum/k));
   v=$1; 
   min=$2;
   k=sum=max=0
}
{
   k++;
   sum+=$2;
   if (min > $2)
      min=$2;
   if (max < $2)
      max=$2
}
END {
   printf("For %s max=%d,min=%d,count=%d,avg=%.2f\n", v, max, min, k, (sum/k))
}' < <(sort -n -k1,2 f)

输出:

For a max=51,min=10,count=5,avg=26.60
For b max=51,min=47,count=2,avg=49.00
For c max=33,min=33,count=1,avg=33.00
于 2013-08-27T10:25:20.677 回答
0

这是一个使用 gawk 甚至 90% 百分位数的版本。

百分位数的定义是维基百科给出的,称为Nearest rank

可以在这里找到函数轮。

#!/bin/bash

gawk '
function round(x, ival, aval, fraction)
{
    ival = int(x)    # integer part, int() truncates

    # see if fractional part
    if (ival == x)   # no fraction
        return ival   # ensure no decimals

    if (x < 0) {
        aval = -x     # absolute value
        ival = int(aval)
        fraction = aval - ival
        if (fraction >= .5)
            return int(x) - 1   # -2.5 --> -3
        else
            return int(x)       # -2.3 --> -2
    } else {
        fraction = x - ival
        if (fraction >= .5)
            return ival + 1
        else
            return ival
    }
}
# the following block processes all the lines
# and populates counters and values
{
    if($1 in counters) {
        counters[$1]++;
    } else {
        counters[$1] = 1;
    }
    i = counters[$1];
    values[$1, i] = $2;
} END {
    for (c in counters) {
        delete tmp;
        min = values[c, 1];
        max = values[c, 1];
        sum = values[c, 1];
        tmp[1] = values[c, 1];
        for (i = 2; i <= counters[c]; i++) {
            if (values[c, i] < min) min = values[c, i];
            if (values[c, i] > max) max = values[c, i];
            sum += values[c, i];
            tmp[i] = values[c, i];
        }

        # The following 3 lines compute the percentile.
        n = asort(tmp, tmp_sorted);
        idx = round(0.9 * n + 0.5); # Nearest rank definition
        percentile = tmp_sorted[idx];

        # Output of the statistics for this group.  
        printf "for %s min = %d, avg = %f, 90 = %d,max = %d, count = %d\n", c, min, (sum / counters[c]), percentile, max, counters[c]; 
    }
}'

要运行执行:

./stats.sh < input.txt

我假设上面的脚本名为 stats.sh 并且您的输入保存在 input.txt 中。

输出是:

for a min = 10, avg = 26.600000, 90 = 51,max = 51, count = 5
for b min = 47, avg = 49.000000, 90 = 51,max = 51, count = 2
for c min = 33, avg = 33.000000, 90 = 33,max = 33, count = 1

这里的解释:

counters 是一个关联数组,键是第 1 列中的值,值是第 1 列中每个值在输入中找到的值的数量。

values 是一个二维 (value_in_column_one, counter_per_value) 数组,它将所有值按第一列中的值分组。

在脚本结束时,最外层循环遍历第 1 列中找到的所有值。最里面的 for 循环分析属于第 1 列中特定值的所有值,并计算所有静态值。

于 2013-08-27T10:53:46.820 回答