Bum*_*ger 3 awk text-processing join
我希望比较两个文件,只打印具有匹配 ID 号且没有重复记录的记录。
我有两个文件:
file1.txt 包含:
Simons 0987768798980
West 09809867678
Vickers 768774564650
Simons 76867790987
Peterson 24346576865
Simons 76867790987
Holister 87879655456
Peterson 87686765766
Run Code Online (Sandbox Code Playgroud)
并且,file2.txt包含:
768774564650 Harry
76867790987 Steve
0987768798980 Mary
0987768798980 Mary
76856009097 Ali
87879655456 Rick
87686765766 Martin
Run Code Online (Sandbox Code Playgroud)
想要的结果是:
Harry Vickers 768774564650
Steve Simons 76867790987
Mary Simons 0987768798980
Rick Holister 87879655456
Martin Peterson 87686765766
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的:
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]=""}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
Harry Vickers 768774564650
Steve Simons 76867790987
Mary Simons 0987768798980
Mary
Rick Holister 87879655456
Martin Peterson 87686765766
Run Code Online (Sandbox Code Playgroud)
我很高兴知道为什么这删除了重复记录的姓氏和 ID 号,但保留了名字。
如果该技术很奇怪或非常规,我们深表歉意。我已经很久没有学习了。
如果我的尝试无法修复或您觉得有更好的方法,我很高兴您以不同的方式产生所需的结果,但请:
使用join如您想保持尽可能简单;
join -1 2 -2 1 -o 2.2 1.1 2.1 <(sort -unk2,2 file1) <(sort -unk1,1 file2) 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
打印部分行的原因是在您的代码中,您没有删除要从数组中删除的值,而是用空字符串替换它们的值。
这会导致检查$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
Run Code Online (Sandbox Code Playgroud)
在单线中:
awk 'NR==FNR{a[$2]=$1;next} $1 in a{print a[$1],$2,$1; delete a[$1]}' file1.txt file2.txt
Run Code Online (Sandbox Code Playgroud)
使用 awk 而不是 join 的优点是简单且易于定制。
缺点是在合并前将第一个文件存储在RAM中,因此无法有效处理大文件。