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
过去该站点使用的另一种方法是使用 的awk
FNR 设施。在这里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。 - 该脚本将处理两个文件的每一行(
file1
beforefile2
),如果之前已经看到过第 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