在 AWK 中打印不重复的数组

在 AWK 中打印不重复的数组

我希望比较两个文件,仅打印具有匹配 ID 号的记录,并且不打印重复记录。

我有两个文件:

file1.txt包含:

Simons 0987768798980
West 09809867678
Vickers 768774564650
Simons 76867790987
Peterson 24346576865
Simons 76867790987
Holister 87879655456
Peterson 87686765766

并且,file2.txt包含:

768774564650 Harry
76867790987 Steve
0987768798980 Mary
0987768798980 Mary
76856009097 Ali
87879655456 Rick
87686765766 Martin

期望的结果是:

Harry Vickers 768774564650
Steve Simons 76867790987
Mary Simons 0987768798980   
Rick Holister 87879655456
Martin Peterson 87686765766

这是我尝试过的:

ARGV[1]==FILENAME{id2lastname[$2]=$1;id2id[$2]=$2}
ARGV[2]==FILENAME{id2firstname[$1]=$2}

$1 in id2id{print id2firstname[$1],id2lastname[$1],id2id[$1],id2firstname[$1]="",id2id[$1]="",id2lastname[$1]=""}

产生以下输出:

Harry Vickers 768774564650   
Steve Simons 76867790987   
Mary Simons 0987768798980   
Mary     
Rick Holister 87879655456   
Martin Peterson 87686765766 

我很高兴知道为什么删除了重复记录的姓氏和 ID 号,但保留了名字。

如果该技术很奇怪或非常规,我们深表歉意。我学习的时间不长。

如果我的尝试无法修复或者您觉得有更好的方法,我很高兴您以不同的方式产生所需的结果,但请:

  • 使用 GAWK (因为我想继续使用它),
  • 尽量保持简单,
  • 并且解释它是如何工作的,这样我就可以学到一些东西。

答案1

打印部分行的原因是,在代码中,您不是删除要从数组中删除的值,而是用空字符串替换它们的值。

这会导致检查$1 in id2id{ ... }评估为true空字符串值。

解决方案是将代码替换id2id[$1]=""delete id2id[$1],然后它应该按预期工作。

这是代码的稍微简化版本:

awk 'NR == FNR { a[$2] = $1; next }
     $1 in a { print a[$1], $2, $1; delete a[$1] }' file1.txt file2.txt

在一行中:

awk 'NR==FNR{a[$2]=$1;next} $1 in a{print a[$1],$2,$1; delete a[$1]}' file1.txt file2.txt

使用 awk 代替 join 的优点是简单且易于定制。

缺点是在合并之前将第一个文件存储在RAM中,因此不能有效地处理大文件。

答案2

根据您的需要使用join,使其尽可能简单;

join -1 2 -2 1 -o 2.2 1.1 2.1 <(sort -unk2,2 file1) <(sort -unk1,1 file2) 2>/dev/null

join在第一个文件的第二个字段上-1 2,以第二个文件的第一个字段-2 1作为键。

-o输出这些字段:
第二个文件中的第二个字段2.2
第一个文件中的第一个字段1.1
和第二个文件中的第一个字段2.1

这将第二个字段上的第一个文件作为键进行数字排序sort -unk2,2 file1
,并将第一个字段上的第二个文件作为数字键进行排序,并从两个文件中sort -unk1,1 file2 删除重复项。-u


awk解决方案:

awk '!second_file{ Ids[$2]=$1; next }
     ($1 in Ids) { print $2, Ids[$1], $1 }' file1 second_file=1 <(sort -u file2)

相关内容