我有一个包含两列和 1000 万行的文件。第一列包含许多重复值,但第 2 列中有一个不同的值。我想删除重复的行并希望仅保留一个使用awk
.注意:文件按第 1 列中的值排序。例如:
1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.
预期产出
1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.
答案1
几个方法:
awk
awk '!a[$1]++' file
这是一种非常简洁的写法:
awk '{if(! a[$1]){print; a[$1]++}}' file
因此,如果当前第一个字段 (
$1
) 不在a
数组中,则打印该行并将第一个字段添加到a
。下次我们看到该字段时,它将位于数组中,因此不会被打印。Perl
perl -ane '$k{$F[0]}++ or print' file
或者
perl -ane 'print if !$k{$F[0]}++' file
这个和上一个基本是一样的
awk
。这-n
导致 perl 逐行读取输入文件并将提供的脚本应用-e
到每一行。将-a
自动在空白处分割每一行并将结果字段保存在@F
数组中。最后,将第一个字段添加到%k
哈希中,如果尚不存在,则打印该行。同样的事情可以写成perl -e 'while(<>){ @F=split(/\s+/); print unless defined($k{$F[0]}); $k{$F[0]}++; }' file
核心工具
rev file | uniq -f 1 | rev
此方法的工作原理是首先反转行,
file
这样如果行是 12 345,那么现在将是 543 21。然后我们使用uniq -f 1
忽略第一个字段,即 543 所在的列。其中有字段file
。此处使用的uniq
效果是过滤掉任何重复的行,每行仅保留 1 个。最后,我们通过另一个相反的操作将线条恢复到原来的顺序。GNU 排序(如建议作者:@StéphaneChazelas)
sort -buk1,1
该
-b
标志忽略前导空格,并且该-u
方法仅打印唯一字段。聪明的一点是-k1,1
.该-k
标志设置要排序的字段。它采用通用格式,即排序时-k POS1[,POS2]
只通过POS2查看字段。POS1
所以,-k1,1
意味着只看第一个字段。根据您的数据,您可能还想添加以下选项之一:-g, --general-numeric-sort compare according to general numerical value -n, --numeric-sort compare according to string numerical value
答案2
如果第一列始终为 5 个字符长,您可以简单地使用uniq
:
uniq -w 5 file
如果没有,请使用awk
:
awk '$1!=a{print $0; a=$1}' file
对于大文件,第一个肯定会更快。