如何使用awk计算异常

How to calculate anomaly using awk

A 有一个文件:

file.txt
1       32
2       34
3       32
4       43
5       25
6       34
7       65
8       34
9       23
10      44

我想在发送列中查找异常:

考虑到第 2 行到第 10 行的值,我的以下脚本打印异常。它没有考虑第 1 行值。

 awk 'FNR==NR{
                f=1;
                if( >= 1 &&  <= 10){
                                                count++;
                                                SUM+=;
                                            };
                next
            }
     FNR==1 && f==1{
                AVG=SUM/count;
                next
                   }
     ( >= 1 &&  <= 10){
                print , -AVG
            }
    ' file.txt file.txt

我的愿望输出:

1       -4.6
2       -2.6
3       -4.6
4       6.4
5       -11.6
6       -2.6
7       28.4
8       -2.6
9       -13.6
10      7.4

我找到了解决方法:

awk '{f=>=1 && <=10}f && NR==FNR{sum+=; c++; next}f{ print , -(sum/c) }' file.txt file.txt

我仍然想知道为什么第一个脚本没有给出正确答案。

OP 中的第一个脚本没有给出正确的值,因为您在文件的第二遍中跳过了第一行。这可以在语句 (FNR==1 && f==1) { AVG=sum/count; next } 中看到。由于 next 语句,您跳过计算与第一条记录的平均值的偏差。

这是在两次传递中对平均值偏差的有效计算:

awk '(NR==FNR){s+=;c++;next}
     (FNR==1){s/=c}
     {print ,-s}' file file

如果 file 在第一列中包含大于 10 或小于 1 的值,但您只想查看 [0,10] 范围内的值,那么您可以执行以下操作:

awk '(<1 || >10) {next}
     (NR==FNR){s+=;c++;next}
     (FNR==1){s/=c}
     {print ,-s}' file file

还有其他优化可以完成,但这些只有在处理非常大的文件(数百万行)时才有用。

由于这只是 2 列文件,因此可以一次性完成 awk 还有:

awk '{map[] = ; s += }
END {mean = s/NR; for (i in map) print i, map[i] - mean}' file

1 -4.6
2 -2.6
3 -4.6
4 6.4
5 -11.6
6 -2.6
7 28.4
8 -2.6
9 -13.6
10 7.4