我有两个文件大文件:
f1.txt:
5020118359 |13ZJ24001218 |20141224|R
5020120475 |13ZJ38000813 |20141204|R
5020127431 |13ZJ38001569 |20141201|R
5020127689 |12ZJ44000606 |20141203|R
5020127728 |13ZJ38001356 |20141203|R
5020127956 |13ZJ62002544 |20141205|R
5020127972 |13ZJ49000082 |20141205|R
5020128325 |13ZJ57000785 |20141210|R
5020128706 |13ZJ38002805 |20141211|R
5020129084 |10XJ70107764 |20141217|R
5020129102 |12ZJ54000041 |20141217|R
f2.txt:
09Y903010552
12ZJ54000041
11XJ62118385
08Y909018946
09Y902011954
11XJ57120346
10XJ70107764
11XJ40165329
09XJ42008336
08Y912021435
11XJ51040272
07Y910027235
输出:
5020129084 |10XJ70107764 |20141217|R
5020129102 |12ZJ54000041 |20141217|R
它将比较第一个文件的第二列和第二个文件的第一列,然后打印第一个文件的匹配记录。
答案1
你尝试过吗awk
?这可以很容易地在awk
.这是一个不同的解决方案:
egrep $(tr '\n' '|' < f2.txt | sed 's/|$//') f1.txt
tr
用于将所有换行符替换为|
,sed
用于删除尾随|
(我打赌有一种更优雅的方法可以做到这一点,而不调用另一个子进程),然后将其用作egrep
= 的参数grep -e
。
答案2
在您展示的简单示例中,您可以使用grep
,将其f2
作为要搜索的模式列表 ( -f
):
$ grep -wf f2.txt f1.txt
5020129084 |10XJ70107764 |20141217|R
5020129102 |12ZJ54000041 |20141217|R
该-w
makegrep
只查找“整个单词”匹配,因此foobar
不被视为 的匹配foo
。
对于更复杂的情况,例如,f2.txt
可以有多个列,或者 中的数据f2.txt
可以出现在 的任何列中,f1.txt
但您只希望它出现在第 1 列上的情况,您可以使用awk
:
$ awk -F'[ |]+' 'NR==FNR{a[$1]++; next}($2 in a )' f2.txt f1.txt
5020129084 |10XJ70107764 |20141217|R
5020129102 |12ZJ54000041 |20141217|R
将-F
字段分隔符设置为一个或多个|
或空格。NR
是当前行号,FNR
是当前文件的行号。当多个文件作为输入给出时,仅当读取第一个文件时两个文件才相等。因此,将为a[$1]++; next
第一个文件的每一行运行。由于第一个文件是,因此将保存数组中f2.txt
的每个第一个字段。跳到下一行。f2.txt
a
next
然后,当我们到达下一个文件时,如果它的第二个字段在数组中,则断言 ($2 in a)
将为 true 并将awk
打印该行。这是断言评估为 true 时的默认操作。它只是一个缩短版本的:
awk -F'[ |]+' '{
if(NR==FNR){
a[$1]++;
}
else if($2 in a ){
print
}
}' f2.txt f1.txt