【问题标题】:How can I remove selected lines with an awk script?如何使用 awk 脚本删除选定的行?
【发布时间】:2010-12-11 09:27:46
【问题描述】:

我正在通过一些 awk 命令传递程序的输出,而且我几乎到了我需要的地方。到目前为止的命令是:

myprogram | awk '/chk/ { if ( $12 > $13) printf("%s %d\n", $1, $12 - $13); else  printf("%s %d\n", $1, $13 - $12)  }  ' | awk '!x[$0]++'

最后一点是穷人的uniq,我的目标没有。如果上面的命令有可能产生如下输出:

GR_CB20-chk_2, 0
GR_CB20-chk_2, 3
GR_CB200-chk_2, 0
GR_CB200-chk_2, 1
GR_HB20-chk_2, 0
GR_HB20-chk_2, 6
GR_HB20-chk_2, 0
GR_HB200-chk_2, 0
GR_MID20-chk_2, 0
GR_MID20-chk_2, 3
GR_MID200-chk_2, 0
GR_MID200-chk_2, 2

我想要的是这个:

GR_CB20-chk_2, 3
GR_CB200-chk_2, 1
GR_HB20-chk_2, 6
GR_HB200-chk_2, 0
GR_MID20-chk_2, 3
GR_MID200-chk_2, 2

也就是说,我只想打印给定标签(第一个“字段”)具有最大值的行。上面的示例代表 at 数据,因为输出将被排序(就好像它已通过 sort 命令进行管道传输一样)。

【问题讨论】:

  • 如果您发现自己在空间和速度方面受到挤压,并且这不是过早的优化,您可以将您的 if ... printf ... else ...printf ... 替换为更短且至少在我的系统上更快的“穷人的abs()” : printf("%s %d\n", $1, (($12 > $13) * 2 - 1) * ($12 - $13))`
  • 另外,请注意,您在/chk/ 上过滤行的awk 命令可以组合到我下面的脚本中(使用mods 来保存适当的“prev”字段而不是整行等。 ) 所以你只打电话给awk 一次。在我的脚本顶部,s 将设置为 (($12 > $13) * 2 - 1) * ($12 - $13) (untested)

标签: sorting awk duplicate-removal


【解决方案1】:

基于我的answer 的类似需求,此脚本使事情井井有条,不会累积大数组。它打印每个组中具有最高值的行。

#!/usr/bin/awk -f
{
    s = substr($0, 0, match($0, /,[^,]*$/))
    if (s != prevs) {
        if ( FNR > 1 ) print prevline
        prevval = $2
        prevline = $0
    }
    else if ( $2 > prevval ) {
        prevval = $2
        prevline = $0
    }
    prevs = s
}
END {
    print prevline
}

【讨论】:

  • 快得多,而且因为内存是一个问题(它是一个嵌入式环境),所以我改用这个作为正确答案。
【解决方案2】:

如果您不需要项目与它们从 myprogram 输出的顺序相同,则可以使用以下方法:

... | awk '{ if ($2 > x[$1]) x[$1] = $2 } END { for (k in x) printf "%s %s", k, x[k] }'

【讨论】:

  • 只是缺少 printf() 中的“\n”。否则完美。
  • 啊,对。我在我的测试版本中有这个,但是在这里输入时忘记了。 :)
猜你喜欢
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2011-06-14
  • 2021-08-05
  • 2020-12-26
相关资源
最近更新 更多