查找并替换重复项

查找并替换重复项

我有一个包含串联电子邮件的文件,如下所示:

id  emails
1   [email protected]
2   [email protected]
3   [email protected],[email protected],[email protected]

每行只有不同的电子邮件,但从一行到另一行可能有重复项,如上面第 1 行和第 3 行所示。我需要从文件中删除重复项,以便文件如下所示:

id  emails
1   [email protected]
2   [email protected]
3   [email protected],[email protected]

这意味着我需要检查每一行及其后面的所有行。考虑到我拥有的数据量,这对于任何类型的迭代脚本都是不可行的。我觉得有一种简单(或至少可行)的方法可以实现这一点awk或者sed但我还没有找到。

答案1

这是一个 sed 解决方案,适用于您的确切输入格式,并且希望运行速度也很快。

sed -rz 's:[ \t]+:,:g;s:$:,:mg;:l;s:,([^,]+),(.*),\1,:,\1,\2,:;tl;s:,$::mg;s:^([^,]+),:\1\t:mg' file.csv

怎么运行的:

“-z”标志加载整个文件,因此以下代码仅应用一次,而不是像默认情况那样应用到每一行。

#transform input format to actual CSV format
s:[ \t]+:,:g;s:$:,:mg;
#loop while the s command can still find and replace
:l;
    #main code: find two identical cell values anywhere and delete the latter
    #on a very big file this can suffer from backtracking nightmare
    s:,([^,]+),(.*),\1,:,\1,\2,:;
tl;
#transform format back
s:,$::mg;s:^([^,]+),:\1\t:mg

答案2

如果您的文件是真正的 csv 文件(simple-csv),如下所示,您可以使用以下awk命令:

输入:

[email protected]
[email protected]
[email protected],[email protected],[email protected]

命令:

awk -F, '{ COMMA="";i=0; while (++i<=NF) {
           $1=$i; printf (!seen[$1]++)?COMMA$i:""; COMMA=","}; print ""
}' infile.csv

输出:

[email protected]
[email protected]
[email protected],[email protected]

如果没有,并且输入就像您问题中给出的那样,您可以使用以下内容:

awk  'NR==1; NR>1{id=$1"\t"; COMMA=$1="";split($0, ar, /,| /); 
    for(i in ar){if(ar[i]!=""){printf(!seen[ar[i]]++)?id""COMMA""ar[i]:""; COMMA=",";id=""}
} print ""}' infile

输出:

id  emails
1       [email protected]
2       [email protected]
3       [email protected],[email protected]

相关内容