【问题标题】:Merge two files using non-exact match in awk在 awk 中使用非完全匹配合并两个文件
【发布时间】:2013-09-10 17:13:40
【问题描述】:

我正在尝试使用 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

我想将文件 2 的第一列添加到文件 1 中的信息中。我希望它匹配两个文件的第一列,但忽略“_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

【问题讨论】:

  • 1mio 行?我建议使用 Perl。
  • @bashophil 我认为问题中显示的 1M 行并不是什么大问题。

标签: regex bash awk merge grep


【解决方案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 命令)。

【讨论】:

  • 抱歉,我不清楚,我将编辑问题以显示所需的输出
  • 您当然可以自己调整输出。我已经进行了更改,但是它引入了冗余,因为您已经将 ID 存储在第一个字段中。如果这解决了您的问题,那么请通过单击旁边的勾号来投票并接受此答案。
【解决方案2】:

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";
}

【讨论】:

  • 我将使用 awk 解决方案,因为我的 perl 不足以理解它在做什么,但是谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 2011-11-24
  • 2016-07-30
  • 1970-01-01
相关资源
最近更新 更多