在awk中使用非完全匹配合并两个文件

时间:2013-09-10 08:47:55

标签: regex bash awk merge grep

我正在尝试使用awk合并2个文件。第一个文件看起来像这样

exm-IND1-200449980  1   202183358
exm-IND1-201453487  1   203186865
exm-IND10-102817747 10  102827758

文件2看起来像这样

exm-IND1-200449980_ver3 -0.0676 0.9988
exm-IND1-201453487_ver1 0.0845  0.0163
exm-IND10-102817747_ver3    -0.1154 0.5166

我希望将File 2的第一列添加到File1中的信息中。我希望它匹配两个文件的第一列,但忽略“_ver3”或“_ver1”字段。我无法在需要时删除此信息。

我认为grep会找到非完全匹配但是当我尝试

grep exm-INDI1-200449980_ver3 file1

没有返回任何内容

我试过了

awk 'NR==FNR{a[$1]=$0; next;}$1 in a {print a[$1]" "$1" "$2" "$3}' file2 file1 > file3

但它没有给我任何输出,我认为因为它只搜索完全匹配?

文件2有~16,000行,文件1有~1,000,000行。

我正在寻找的输出将是这样的,

exm-IND1-200449980 1 202183358 exm-IND1-20449980_ver3
exm-IND1-201453487 1 203186865 exm-IND1-201453487_ver1

2 个答案:

答案 0 :(得分:1)

这应该可以解决问题:

$ awk -F'_| *' 'FNR==NR{a[$1]=$0;next}$1 in a{print a[$1],$1"_"$2}' file1 file2
exm-IND1-200449980  1   202183358 exm-IND1-200449980_ver3
exm-IND1-201453487  1   203186865 exm-IND1-201453487_ver1
exm-IND10-102817747 10  102827758 exm-IND10-102817747_ver3

确保你有足够的内存来容纳file1,虽然根据我的估计,文件应该小于50兆字节,这对过去十年制造的大多数机器来说都不会有问题。如果大小确实成为问题,您应该考虑将文件拆分为块(您可以使用split命令)。

答案 1 :(得分:1)

Perl解决方案:

#!/usr/bin/perl
use warnings;
use strict;

my %f2;
open my $F2, '<', 'file2' or die $!;
while (<$F2>) {
    my ($id, $num) = split ' ', $_, 3;
    $id =~ s/_ver[0-9]+//;
    $f2{$id} = $num;
}

open my $F1, '<', 'file1' or die $!;
while (<$F1>) {
    my ($id) = split ' ', $_, 2;
    chomp;
    print $_, "\t", $f2{$id}, "\n";
}