unix - 根据匹配字段删除第一个重复行并保留第二个匹配行

标签 unix awk duplicates match

  1. 输入文件有 3 个字段。每个字段由 | (PIPE) 分隔。
  2. 第一个字段是关键字段并已排序。第一个字段中的每个键可能出现一次或两次。
  3. 如果相同的键在第一个字段中存在两次,则删除行 第一次出现的行,不要删除第二次出现的行。
  4. 如果某个键仅出现一次,则不要删除该行。
  5. 第三个字段中的输入数据在整个文件中是唯一的。

尝试了以下命令,该命令保留第一个重复行并删除其余的重复行。 awk 命令中是否有任何选项可以删除第一个匹配的重复行并保留第二个匹配的行。 awk 以外的命令也可以。输入文件大小可以是 50 GB 大小。我现在正在 12 GB 文件上进行测试。

awk -F'|' '!a[$1]++'

输入文件内容:

1|xxx|{name: "xyz"}
2|xxx|{name: "abcfgs"}
3|xxx|{name: "egg"}
4|xxx|{name: "eggrgg"}
5|xxx|{name: "xsdsyzsgngn"}
5|xxx|{name: "gbgnfxyz"}
6|xxx|{name: "xyz"}
7|xxx|{name: "xynfnfnnnz"}
7|xxx|{name: "bvbv"}
8|xxx|{name: "xyz"}
9|xxx|{name: "xyz"}
....

处理输入文件后的预期输出:

1|xxx|{name: "xyz"}
2|xxx|{name: "abcfgs"}
3|xxx|{name: "egg"}
4|xxx|{name: "eggrgg"}
5|xxx|{name: "gbgnfxyz"}
6|xxx|{name: "xyz"}
7|xxx|{name: "bvbv"}
8|xxx|{name: "xyz"}
9|xxx|{name: "xyz"}
....

编辑

尝试了@RavinderSingh13@RomanPerekhrest分别提供的以下解决方案。

对于 12GB 输入文件,以下解决方案第一次运行需要 1 分 20 秒,第二次运行需要 1 分 46 秒:

awk '
BEGIN{
  FS="|"
}
!a[$1]++{
  b[++count]=$1
}
{
  c[$1]=$0
}
END{
  for(i=1;i<=count;i++){
    print c[b[i]]
  }
}
' Inputfile  > testawk.txt

对于 12GB 输入文件,以下解决方案第一次运行耗时 2 分 31 秒,第二次运行耗时 4 分 43 秒,第三次运行耗时 2 分钟:

awk -F'|' 'prev && $1 != prev{ print row }{ prev=$1; row=$0 }END{ print row }' Inputfile > testawk2.txt

这两个解决方案都按预期工作。在进行更多性能测试后,我将使用上述任何一种。

最佳答案

使用awk表达式高效:

awk -F'|' 'prev && $1 != prev{ print row }{ prev=$1; row=$0 }END{ print row }' file

“魔法”是基于捕获每个当前记录(有效地覆盖它,而不需要不断积累)并对下一个行进行分析。

示例输出:

1|xxx|{name: "xyz"}
2|xxx|{name: "abcfgs"}
3|xxx|{name: "egg"}
4|xxx|{name: "eggrgg"}
5|xxx|{name: "gbgnfxyz"}
6|xxx|{name: "xyz"}
7|xxx|{name: "bvbv"}
8|xxx|{name: "xyz"}
9|xxx|{name: "xyz"}

关于unix - 根据匹配字段删除第一个重复行并保留第二个匹配行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59156401/

相关文章:

c++ - 如何枚举 POSIX/c c++ 目录中的所有文件?

linux - 如何将所有文件从一个目录移动(并覆盖)到另一个目录?

java - 使用 jstack 获取线程转储

regex - 使用 sed 删除正则表达式模式之间的多行文本 block

javascript - 使用 Javascript 复制表单

arrays - 使用特定条件在一行中查找重复值

unix - GNU screen 命令不显示状态栏

linux - Perl/Linux 用另一个文件的内容过滤大文件

python - 合并两个排序的列表列表,如果内部列表中有重复值,则只保留第一个列表中的值

bash - 文件操作循环