awk:从列中找到最小的10个值

时间:2016-02-05 02:45:02

标签: awk

我有一个像这样排列的文件:

a  123
b 45
c -23
d 166

我是awk的新手,我想找到第2列中的十(或x)个最低数字,然后在新文件中打印这些行。

目前我们使用以下代码并观察结果,看看我们是否大约有十个。如果没有,我们将-5.0更改为其他内容,依此类推:

cat input.txt | awk '{if($2 < -5.0) {print $1" "$2}}' >> output.txt

2 个答案:

答案 0 :(得分:6)

如果没有AWK,您可以轻松完成此任务:

$ sort -nk 2 input.txt | head -10 > output.txt

对输入文件进行排序并打印前10行(第2列中的值最低)。如果您的输入文件特别大,这可能不合适。此sort可能使用O( N log N )排序算法(对于 N 输入行)。

如果您只想要最低限度,AWK中的解决方案将是一个单行。在这种情况下,它有点棘手,因为您必须保持多个最低值。尝试这样的事情:

<强> lowest.awk

#!/usr/bin/awk -f
BEGIN{if (X=="") X=10; s=0}
{ # insert new value in order
    for (i=0; i<s && $2>a[i]; ++i);
    if (s==X && i==s) next
    for (j=s; j>i; --j) {
        a[j] = a[j-1]
        b[j] = b[j-1]
    }
    a[i] = $2
    b[i] = $0
    if (s<X) s++
}
END{ # print stored lines
    for (i=0; i<s; ++i)
        print b[i]
}

要在命令行上运行:

$ awk -f lowest.awk infile.txt > outfile.txt

您可以使用-v X=10从命令行指定要打印的最低值 X

$ awk -v X=10 -f lowest.awk infile.txt > outfile.txt

但默认为10。

将每个值(在第2列中)与数组a的每个元素进行比较,并在需要的地方插入新值。数组b存储要在末尾打印的整行($0)。 ab的(已使用)大小为s

通常,您应该使用类似for (i in a)的内容遍历数组中的条目,但在这种情况下,a[s]处有一个额外的条目,在打印结果时必须忽略它,因此for (i=0; i<s; ++i)块中的END格式。

在最坏的情况下,每个 N 值都与a中的 X 值进行比较。所以这是O( XN ),这是对O( N log N sort版本的改进。此外,它需要更少的内存,因为您只在内存中存储O( X )值而不是所有 N 行。

请注意,这会通过插入维护订单。在 X = N 的情况下,您将保留所有值并按顺序列出它们 - 换句话说就是排序。当 X 接近 N XN )公式接近O( N 2 ) >,这是插入排序算法的复杂性。所以这个AWK版本只比O( N log N )基于排序的方法更有效,其中 X 远小于 ñ

答案 1 :(得分:1)

@ e0k的sort|head一般是正确的UNIX解决方案,但如果你出于某种原因必须使用awk,那么使用GNU awk for sorted_in:

$ awk -v x=2 '{a[NR]=$2; b[NR]=$0}
    END{ PROCINFO["sorted_in"]="@val_num_asc"; for (i in a) if (x-->0) print b[i] }' file
c -23
b 45

$ awk -v x=3 '{a[NR]=$2; b[NR]=$0}
    END{ PROCINFO["sorted_in"]="@val_num_asc"; for (i in a) if (x-->0) print b[i] }' file
c -23
b 45
a  123
相关问题