bash合并唯一id的表

时间:2015-10-09 22:20:56

标签: bash perl replace uniqueidentifier col

我有两个类似的'表格式'文本文件,每个文件长达数百万条。在inputfile1中,唯一标识符是两个其他列中的值的合并(它们都不是唯一的标识符)。在inputfile2中,唯一标识符是两个字母,后跟一个随机的四位数字。

如何将inputfile1中的唯一标识符替换为inputfile2中相应的唯一标识符?第一个表中的所有记录都存在于第二个表中,但不是相反。以下是文件的玩具示例。

输入文件1:

Grp Len ident   data
A   20  A_20    3k3bj52
A   102 A_102   3k32rf2
A   352 A_352   3w3bj52
B   60  B_60    3k3qwrg
B   42  B_42    3kerj52
C   89  C_89    3kftj55
C   445 C_445   fy5763b

输入文件2:

Grp Len ident
A   20  fz2525
A   102 fz5367
A   352 fz4678
A   356 fz1543
B   60  fz5732
B   11  fz2121
B   42  fz3563
C   89  fz8744
C   245 fz2653
C   445 fz2985
C   536 fz8983

期望的输出:

Grp Len ident   data
A   20  fz2525  3k3bj52
A   102 fz5367  3k32rf2
A   352 fz4678  3w3bj52
B   60  fz5732  3k3qwrg
B   42  fz3563  3kerj52
C   89  fz8744  3kftj55
C   445 fz2985  fy5763b

我的临时计划是:

  1. 以input1(easy)
  2. 的样式为input2生成额外的标识符
  3. 从输入2中过滤掉未发生输入1(艰难)
  4. 的行
  5. 然后坚持使用input1(easy)
  6. 中的数据

    我或许可以在R中做到这一点,但数据庞大而且复杂,我想知道bash或perl中是否存在某种方式。任何正确方向的提示都会很好。

1 个答案:

答案 0 :(得分:1)

根据我的评论,假设GrpLen值在两个文件中的顺序相同,这应该对您有用

本质上,它从第一个文件中读取一行,然后从第二个文件读取,从每个记录中形成Grp_Len键,直到找到匹配的条目。那么这只是构建新输出记录的问题

use strict;
use warnings;

open my $f1, '<', 'file1.txt';
print scalar <$f1>;
open my $f2, '<', 'file2.txt';
<$f2>;

while ( <$f1> ) {

    my @f1 = split;

    my @f2;
    while () {
        @f2 = split ' ', <$f2>;
        last if join('_', @f2[0,1]) eq $f1[2];
    }

    print "@f2 $f1[3]\n";
}

输出

Grp Len ident   data
A 20 fz2525 3k3bj52
A 102 fz5367 3k32rf2
A 352 fz4678 3w3bj52
B 60 fz5732 3k3qwrg
B 42 fz3563 3kerj52
C 89 fz8744 3kftj55
C 445 fz2985 fy5763b


更新

这里的另一个版本是相同的,只是它从第一个文件中列标题的间距构建一个printf格式字符串。这导致更整洁的输出

use strict;
use warnings;

open my $f1, '<', 'file1.txt';
my $head = <$f1>;
print $head;
my $format = create_format($head);

open my $f2, '<', 'file2.txt';
<$f2>;

while ( <$f1> ) {

    my @f1 = split;

    my @f2;
    while () {
        @f2 = split ' ', <$f2>;
        last if join('_', @f2[0,1]) eq $f1[2];
    }

    printf $format, @f2, $f1[3];
}

sub create_format {
    my ($head) = @_;
    my ($format, $pos);

    while ( $head =~ /\b\S/g ) {
        $format .= sprintf("%%-%ds", $-[0] - $pos) if defined $pos;
        $pos = $-[0];
    }

    $format . "%s\n";
}

输出

Grp Len ident   data
A   20  fz2525  3k3bj52
A   102 fz5367  3k32rf2
A   352 fz4678  3w3bj52
B   60  fz5732  3k3qwrg
B   42  fz3563  3kerj52
C   89  fz8744  3kftj55
C   445 fz2985  fy5763b