在awk中嵌套for循环以计算匹配值的字段数

时间:2015-05-01 19:06:48

标签: loops awk

我有一个包含两列(140万行)的文件,如下所示:

CLM MXL
0 0
0 1
1 1
1 1
0 0
29 42
0 0
30 15

我想计算每种可能的价值组合的实例;例如,如果有列数CLM等于0且列MXL与1匹配的行数为x,我想打印:

0 1 x

由于列CLM的最大值为188且列MXL的最大值为128,我试图在awk中使用嵌套的for循环,如下所示:

awk '{for (i=0; i<=188; i++) {for (j=0; j<=128; j++) {if($9==i && $10==j) {print$0}}}}' 1000Genomes.ALL.new.txt > test

但这只打印出原始文件,这是有意义的,我只是不知道如何正确编写for循环,为每个值组合打印出一个文件,然后我可以wc,或打印出一个每个组合的计数文件。在awk,bash脚本,perl脚本中的任何解决方案都会很棒。

1 个答案:

答案 0 :(得分:3)

1。纯awk解决方案

$ awk 'NR>1{c[$0]++} END{for (k in c)print k,c[k]}' file | sort -n
0 0 3
0 1 1
1 1 2
29 42 1
30 15 1

如何运作

代码使用单个变量cc是一个关联数组,其键是文件中的行,其值是出现的次数。

  • NR>1{c[$0]++}

    对于除第一行(具有标题)之外的每一行,这会增加该行中组合的计数。

  • END{for (k in c)print k,c[k]}

    这将打印出最终的计数。

  • sort -n

    这只是为了美学:它以可预测的顺序输出输出线。

2。使用uniq -c

的备选方案
$ tail -n+2 file | sort -n | uniq -c | awk '{print $2,$3,$1}'
0 0 3
0 1 1
1 1 2
29 42 1
30 15 1

如何运作

  • tail -n+2 file

    这将打印除文件第一行以外的所有行。这样做的目的是删除列标题。

  • sort -n | uniq -c

    对行进行排序,然后对重复项进行计数。

  • awk '{print $2,$3,$1}

    uniq -c将计数放在首位,您希望计数成为最后一项。这只是将列重新排列为您想要的格式。