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

标签 awk

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

a  123
b 45
c -23
d 166

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

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

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

最佳答案

不用 AWK 也可以轻松做到这一点:

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

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


如果您只想要最少的,AWK 中的解决方案就是单行代码。在这种情况下有点棘手,因为您必须维护多个最低值。尝试这样的事情:

最低.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)。 a 的(已用)大小和 bs .

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

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

请注意,这通过插入来维护顺序。当 X=N 时,您将保留所有值并按顺序列出它们——换句话说就是排序。当 X 接近 NXN) 公式接近 O(N2) >,这是插入排序算法的复杂度。因此,此 AWK 版本仅比基于排序的 O(N log N) 方法更有效,其中 X 远小于 N.

关于awk:从列中找到最小的 10 个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35215462/

相关文章:

AWK 在第 3 列中查找重复值。打印整行

awk 语法错误 a[$1]

awk - 匹配列一个单独的文件并将匹配项附加到文件

linux - 根据列匹配从两个输入文件创建输出文件

regex - 如何使用 awk 打印匹配的正则表达式模式?

awk - 将字符串中的数字替换为包含替换数字个数的模式

linux - 获取 "-("和 ")-"之间的字符串,linux 目录

linux - awk 中非常奇怪的行为

awk - 使用 awk 的移动平均线

ubuntu - awk 脚本没有运行,好像我跳过了括号,但我已经数过了,它们的数量是偶数