我有一个多字段文本文件。我想要一个命令,它将结合sort -n -u -k
和uniq -c
的行为,也就是说,对某个密钥字段上的文件进行排序,并提供预处理或推迟到原始行的重复数。此时,我要么对某个关键字进行排序,用sort -n -u -k
获得没有重复数的第一行重复行,要么通过提取关键字字段用uniq -c
计算重复数。
你能建议一个同时实现这两种行为的命令吗?
文件示例(键列可以是任何指定的):
4549 1 22656489 63452157 3235 1116 612 532275 6009800 534075 6012488 477375 5995844 533175 6011144 8388615 236
4549 2 22656489 63452158 3214 1116 613 532275 6009825 534075 6012488 477375 5995831 533175 6011157 8388615 236
4549 3 22656489 63452159 3193 1116 614 532275 6009850 534075 6012488 477375 5995819 533175 6011169 8388615 236
4549 4 22656489 63452160 3173 1116 615 532275 6009875 534075 6012488 477375 5995806 533175 6011182 8388615 235
4549 5 22656489 63452161 3152 1116 616 532275 6009900 534075 6012488 477375 5995794 533175 6011194 8388615 235
4549 6 22656489 63452162 3131 1116 617 532275 6009925 534075 6012488 477375 5995781 533175 6011207 8388615 235
4549 7 22656489 63452163 3111 1116 618 532275 6009950 534075 6012488 477375 5995769 533175 6011219 8388615 235
4549 8 22656489 63452164 3091 1116 619 532275 6009975 534075 6012488 477375 5995756 533175 6011232 8388615 234
4549 9 22656489 63452165 3070 1116 620 532275 6010000 534075 6012488 477375 5995744 533175 6011244 8388615 234
4549 10 22656489 63452166 3050 1116 621 532275 6010025 534075 6012488 477375 5995731 533175 6011257 8388615 234
4549 11 22656489 63452167 3030 1116 622 532275 6010050 534075 6012488 477375 5995719 533175 6011269 8388615 234
使用decorate-sort-uncorate,您可以将要进行处理的字段附加到数据中,进行处理,并删除多余的字段。E.g在字段17和字段5:上排序
awk '{print $0 OFS $17 OFS $5}' test_s | sort -n -k18 -k19 | uniq -c -f17 | awk '{NF=18;print}'
首先追加关键字段,然后追加sort
和uniq
,然后只保留uniq
和原始字段相加的计数。
根据我目前的理解,您希望指定一个或多个列用作键,并获得一个结果,每个输出行显示该键的多重性。在这种情况下,假设您的数据在一个名为"data"的文件中,并且我们希望第17列作为密钥:
$ awk '{print $17}' data | sort -n | uniq -c
4 234
4 235
3 236
因此,236的值在测试数据的第17列中总共出现了3次。或者,假设您想要第6、8、1和3列作为关键字(按顺序):
$ awk '{print $6,$8,$1,$3}' data | sort -n | uniq -c
11 1116 532275 4549 22656489
对于这个键,所有11行都是重复的。
这种方法有三个步骤。首先,我们让awk
按照您想要的顺序选择您想要的列。其次,sort -n
在键上对它们进行数字排序。最后,uniq
计数重复。
UPDATE:如上所述,假设我们希望使用第6、8、1和3列作为关键字,但根据您的评论,我们希望保留其中一行。在这种情况下,我们指示awk将原来的17列放在键之前,我们告诉sort在键上排序(第18+列),然后我们指示uniq忽略前17列:
awk '{print $0,$6,$8,$1,$3}' data | sort -k18 -n | uniq -f 17 -c
对于您的样本数据,这将导致:
11 4549 10 22656489 63452166 3050 1116 621 532275 6010025 534075 6012488 477375 5995731 533175 6011257 8388615 234 1116 532275 4549 22656489
如果您只想打印原始的17列,那么我们可以使用perl只显示前17列,并裁剪关键:
awk '{print $0,$6,$8,$1,$3}' data | sort -k18 -n | uniq -f 17 -c | perl -nle '@a=split;print join " ", @a[0..17]'
结果是:
11 4549 10 22656489 63452166 3050 1116 621 532275 6010025 534075 6012488 477375 5995731 533175 6011257 8388615 234