![如何打印第 1 列中唯一值出现的增量计数](https://linux22.com/image/61866/%E5%A6%82%E4%BD%95%E6%89%93%E5%8D%B0%E7%AC%AC%201%20%E5%88%97%E4%B8%AD%E5%94%AF%E4%B8%80%E5%80%BC%E5%87%BA%E7%8E%B0%E7%9A%84%E5%A2%9E%E9%87%8F%E8%AE%A1%E6%95%B0.png)
我正在尝试解决这个问题,我需要增量计数,然后打印制表符分隔文本文件的第 1 列中唯一值的计数。这是一个例子:
Apple_1 1 300 Apple_2 1 500 Apple_2 500 1500 Apple_2 1500 2450 Apple_3 1 1250 Apple_3 1250 2000
所需的输出是:
Apple_1 1 300 1 Apple_2 1 500 1 Apple_2 500 1500 2 Apple_2 1500 2450 3 Apple_3 1 1250 1 Apple_3 1250 2000 2
我知道我可以通过打印 NR 来打印 awk 中的行号,但我不知道如何为第 1 列的每个唯一值重置它。
感谢您提供的任何帮助,我很感激。
答案1
Awk 中解决此类问题的标准技巧是使用关联计数器数组:
awk '{ print $0 "\t" ++count[$1] }'
这会计算每行中第一个单词出现的次数。这不完全是你所要求的,因为
Apple_1 1 300
Apple_2 1 500
Apple_1 500 1500
会产生
Apple_1 1 300 1
Apple_2 1 500 1
Apple_1 500 1500 2
(当我们看到 时, 的计数Apple_1
不会重置Apple_2
),但如果输入已排序,那就没问题了。
否则,您需要跟踪计数器和上次看到的密钥:
awk '{ if (word == $1) { counter++ } else { counter = 1; word = $1 }; print $0 "\t" counter }'
答案2
这个答案没有给出您指定的确切输出,但其他用户可能更感兴趣。
如果你不需要增加的计数,但只是每个唯一值的计数,您可以使用更简单的:
cut -f1 file.txt | sort | uniq -c
(请注意,这cut
取决于制表符分隔符,而不仅仅是任何空格。)
实际上,由于您的文件已经在第一个字段上排序,因此您不需要对其进行排序:
cut -f1 file.txt | uniq -c
如果您想将它们作为新的第四列包含在原始文件中,您可以使用join
:
cut -f1 file.txt | uniq -c | join -2 2 file.txt -
(join
取决于排序的输入。)
所提供输入的输出为:
Apple_1 1 300 1
Apple_2 1 500 3
Apple_2 500 1500 3
Apple_2 1500 2450 3
Apple_3 1 1250 2
Apple_3 1250 2000 2
请注意,join
以直观的方式读取空白分隔符(无论是制表符还是空格),但仅输出分隔符的一个空格。如果您想要恢复选项卡,请通过管道传输到tr ' ' '\t'