2017-04-10 46 views
2

我想使用gawk 4.1.4来计算文件的字段12中不同值的数量,并且还要计算每个值出现的次数。我有两个简短的程序,它们给了我第一个问题的不同答案,并且我无法解释为什么。gawk行为我不明白

{if(a[$12]++==1){count++}} END {print count} 

...给人435176的结果,而

{a[$12]++} END {for (i in a){count++};print count} 

...给人599845的结果。

你能解释这种行为,并告诉我哪个值是正确的吗?我在Windows(ezwinport)下运行,字段分隔符是选项卡。

回答

2

第一个是错误的每个独特价值的独特发生次数(逻辑,语法上不,谢谢你强调的事实,@GeorgeVasiliou),因为你需要++==++a[$1]==1

$ awk '{if(++a[$1]==1){count++}} END {print count}' foo 
3 

噢,我的测试foo

$ cat foo 
1 
1 
1 
2 
2 
3 
+1

是的,或者可以使用'{if(a [$ 12] ++ == 0){count ++}} END {print count}'但我觉得这个代码稍微难一点。 –

+2

好东西!我唯一的问题是,'count'不是必需的,你可以使用数组值来使它工作! – Inian

+0

@Inian Tru dat。由于OP中提到了gawk(lol),我们可以用'length()'得到不同值的数目:'{a [$ 1] ++} END {print length(a)}',对吧? –

2

显然第2一看起来不错! 已经存储了count,你并不需要一个单独的变量

您使用的是count来标识唯一的发生是错误的无论是在意义上的情况下,它是每并不跟踪的方式独特的实例。

使用数组本身的值。

在推导count

{if(a[$12]++==1){count++}} END {print count} 

的逻辑是,但它的作用其实是递增运算符$12现场发生因为它是在跟踪的第二次变量count。因此,您在输出中看到的较小的计数。

在另一方面,

{a[$12]++} END {for (i in a){count++};print count} 

几乎是正确的,但你并不需要一个count变量,你已经拥有它存储阵列a的价值的一部分,由独特的价值索引$12。做好上面的也一样

{a[$12}++; next} END {for (i in a) print a[i]} 

一个小例子来说明它,

cat file 
1 2 3 
1 2 3 
1 2 1 
1 1 1 
2 3 1 
3 4 1 

假设我所担心的唯一实例及其发生在$2计数。做你的第一个例子,

awk '{if(a[$2]++==1){count++}}END {for (i in a) print i,a[i],count}' file 
1 1 1 
2 3 1 
3 1 1 
4 1 1 

看到的count错误值在最后一栏打印,如果你能仔细看到它,变量甚至没有保持跟踪每个实例计数而是对所有公共变量实例。

第二种方法,看似看起来不错,但打印count4针对例如不明确,假设多个实例,并可能会出现他们的计数。正确的方法是做,

awk '{a[$2]++; next}END {for (i in a) print i,a[i]}' file 
1 1 
2 3 
3 1 
4 1 

这里,而不是count,该a[i]拥有的第2列

+0

这两个片段的目的是简单地计算唯一值的数量,同时总结每个值的计数但不打印它们。 –

+0

@MattWenham:够公平的,不要打印它们,只需使用数组值即可。 – Inian