在管道 delim 文件中查找第五列的匹配项

在管道 delim 文件中查找第五列的匹配项
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

我需要在第 5 列的文件 1 和文件 2 中找到匹配的记录。因此,从上面我需要在输出中返回:

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

非常感谢,

答案1

方法#1:grep 和 awk

您可以使用此代码片段来执行此操作:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

细节

使用的位awk解析第一个文件,file1提取所有第五列。然后将这些值用作 的列表grep,它将打印第二个文件中包含匹配项的任何行。

使用此方法的注意事项

file1此方法将匹配中出现的任何第五列file2

方法#2:只需 awk

过去该站点使用的另一种方法是使用 的awkFNR 设施。在这里awk将迭代 2 个文件,逐行遍历第二个文件,查找第一个文件中的每一行。

像这样的方法就可以做到。将以下内容放入文件中cmds.awk

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

然后您可以按如下方式运行:

$ awk -F '|' -f cmds.awk file1 file2

笔记:您可以改用此awk模式:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

例子

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

使用此方法的注意事项

此方法只能处理来自 的每个电子邮件地址的单个实例file1。因此,如果有 2 行的第 5 列值相同,则无法区分它们。考虑到您在 OP 中的要求,这似乎是可以接受的。

加入并排序

您还可以使用join和来执行此操作sort

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

这将使用分隔符|并将排序后的文件连接到第五列。这种方法会打印file1和中的匹配项file2,因此我们用来sed将第二个匹配项从末尾切掉。

例子

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578

答案2

我会用 perl 完成整个事情:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -a激活自动字段分裂到数组中@F
  • -F'\|'设置 to 的字段分隔-a|
  • 对于处理的每一行,将第 5 个字段(在 Perl 中从数组索引开始0)保存为散列键($k{$F[4]}++并将其值增加 1。第二次看到某个字段时,该值将为 2。
  • 该脚本将处理两个文件的每一行(file1before file2),如果之前已经看到过第 5 个字段,即 if$k{$F[4]}大于 1,则打印该行。

这假设第五列在相同的文件。如果情况并非如此,并且某些列可能在同一文件中重复,请改用以下命令:

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 

答案3

如果文件大小相当,最佳解决方案是sort这两个文件都按您感兴趣的列排列,然后join他们在那一栏旁边。如果文件大小为NM则渐近运行时间为O(N*log(N)+M*log(M))

如果其中一个文件比另一个文件小得多,那么O(N*M)其他答案中的解决方案会更好。

相关内容