【发布时间】:2020-03-28 02:20:53
【问题描述】:
- 输入文件有 3 个字段。每个字段由 | (PIPE) 分隔。
- 第一个字段是关键字段并已排序。第一个字段中的每个键可能出现一次或两次。
- 如果相同的键在第一个字段中存在两次,则删除 第一次出现,不要删除第二次出现的行。
- 如果一个键只出现一次,则不要删除该行。
- 第三个字段中的输入数据在整个文件中都是唯一的。
尝试了以下命令,该命令保留第一个重复行并删除其余重复行。 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
两种解决方案都按预期工作。在进行几次性能测试后,我将使用上述任何一种。
【问题讨论】:
-
我没有从预期的输出中看到任何重复的删除。请详细说明。
-
@JamesBrown 做到了。关键是
$1 -
第三个、第四个……应该像第一个一样被删除吗? NO重复的情况呢,还需要看一审吗?
-
在你的例子中,是前缀 '5|xxx|'只是意味着输入文件 xxx 的第 5 行?或者它是输入的一部分?
-
为什么预期的输出包含第 1 行中的“xyz” - 是否应该因为第 6 行中的“xyz”而将其删除?
标签: unix awk duplicates match