按重复项对列进行排序并保留第一个出现的项

按重复项对列进行排序并保留第一个出现的项

我有一个文件如下

1:A
2:B
3:A

我需要的输出是:

1:A
2:B

由于第三个条目的第二列包含 A,就像第一个条目一样,因此将其删除。它还需要区分大小写。

这是一个非常大的文件,因此节省时间会很好。

我已经尝试过,但它似乎只打印独特的行

sort -u -t':' -k3,3 file

答案1

使用sort

正如埃德在他的书中所说评论,您的sort命令是对第三个字段进行排序,而实际上您只有两个字段(这:是字段分隔符)。因此,要修复它,请将密钥替换为32

但是,当记录按其键值而不是按行/记录号排序时,源文件中的原始记录顺序会变得混乱:

$ sort -u -t':' -k2,2 test.txt 
1:A
2:B
6:C
5:a
4:b
$

这可能是不是你想要什么。不过,通过再次通过管道输出可以轻松解决此问题sort

$ sort -u -t':' -k2,2 test.txt | sort 
1:A
2:B
4:b
5:a
6:C
$

笔记:正如您所说,您有一个大文件,为了加快速度,您可能需要考虑使用--parallel标志1

sort --parallel=<n> -u -t':' -k2,2 test.txt | sort --parallel=<n>

您何时<n>拥有可用的核心数。

使用awk

扩展示例文件,如果原始数据位于名为 的文件中test.txt,如下所示:

1:A
2:B
3:A
4:b
5:a
6:C

并且,再次将 视为:字段分隔符,那么您可以使用awk2

例如这一行:

awk 'BEGIN{FS=":"}{if (!seen[$2]++)print $0}' test.txt

给出以下结果:

$ awk 'BEGIN{FS=":"}{if (!seen[$2]++)print $0}' test.txt 
1:A
2:B
4:b
5:a
6:C
$

您可以通过查看逻辑来了解其工作原理,使用

$ awk 'BEGIN{FS=":"}{print !seen[$2]++}' test.txt 
1
1
0
1
1
1
$
  • 首先,字段分隔符用 指定FS=":"
  • 其次,否定运算符为第二个字段条目提供“真”结果,而该结果尚未然而被看见了。
  • 最后,print $0打印整个记录,即当前行。

将其放入 shell 脚本3而不是awk脚本中会得到:

#!/bin/sh

awk -F':' '
  (!seen[$2]++) {
    print $0
  }
' "$1"

参考:

1这个回答大文件如何排序?

2这个回答根据三列中的两列中的信息保留唯一行

3这个回答在 awk 脚本头中指定其他标志

相关内容