基于一列匹配和打印两个文件时使用awk

3

我有两个文件(分隔符为制表符)

文件1:db.txt

string1 string2 string3 001 string4
string5 string6 string7 002 string8
string9 string10 string11 003 string12

文件2:query.txt
id1 001
id2 003

我想要匹配文件1和文件2,如果匹配成功,则打印db.txt的第1到5列以及query.txt的第1列。
我尝试使用awk,以下是我的代码:
awk 'BEGIN{FS=OFS="\t"}NR==FNR{a[$2]=$4;next}$4 in a{print $1,$2,$3,$4,$5,a[$1]}' query.txt db.txt

但是我只得到了一个带有匹配项(?至少我认为是这样)和 db.txt 文件列的文件。

编辑:我的更复杂的 db2.txt

string1 <TAB> string2 <TAB> 9999 abc dehi [way:pn9999] <TAB> 001 <TAB> org; string3 string4
string5 <TAB> string6 <TAB> 9999 dwd meti [way:pn8999] <TAB> 002 <TAB> org2; string7
string8 <TAB> string9 <TAB> 9999 dwd meti [way:pn7999] <TAB> 003 <TAB> org4; string10

那个键值总是在db文件的第四个字段吗? - James Brown
有时候是不同的键,但是是的。 - rororo
跟进问题:我有两个略微不同的文件存在问题。我想要基于第一列匹配这两个文件,当匹配成功时,应该打印出文件1和文件2的第二列。以下是我的代码:awk 'BEGIN{FS=OFS="\t"} FNR == NR { a[$1] = $1; next } $1 in a { print a[$2], $2 }' - rororo
“将其发布为新问题,您会得到更多的关注。” - James Brown
2个回答

1
AMD$ cat f1
id1 001
id2 003

AMD$ cat f2
string1 string2 string3 001 string4
string5 string6 string7 002 string8
string9 string10 string11 003 string12

AMD $ awk 'NR==FNR {a[$2]=$1; next} {for(i in a) if(index($0,i)) print a[i], $0}' f1 f2
id1 string1 string2 string3 001 string4
id2 string9 string10 string11 003 string12

根据f1中记录的数量以及是否始终有5个字段需要进行检查,可能更有效地使用for循环字段。当然,我们无法猜测记录的数量。 - James Brown
db.txt 相对于 query.txt 来说非常庞大。 - rororo

1
您可以这样使用 awk

awk 'BEGIN{FS=OFS="\t"} FNR == NR { a[$2] = $1; next }
$4 in a { print $0, a[$4] }' query.txt db.txt

string1 string2 string3 001 string4 id1
string9 string10 string11 003 string12 id2

是的,这对我发布的示例完美地起作用,但不知何故,它对我的文件无效;我的列中有一些空格。 - rororo
默认情况下,空格是字段分隔符。你能否在问题中发布真实的示例数据,以便我能够理解并修改我的答案。 - anubhava
感谢您的耐心等待,我已经添加了一个更好的例子来说明db.txt - rororo
1
好的,尝试使用制表符作为分隔符:awk 'BEGIN{FS=OFS="\t"} FNR == NR { a[$2] = $1; next } $4 in a { print $0, a[$4] }' query.txt db.txt - anubhava
1
非常感谢,这解决了问题!我之前尝试过 FS=OFS 选项,但不知怎么就失败了。 - rororo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接