如何将一个文件中的值与另一个文件中的值匹配?

时间:2016-06-15 17:58:57

标签: perl awk

有两个输入文件,如下面的行所示。

input1中的第3列和第4列包含范围(例如第一行中的178

input2中的第2列包含单个位置值(第一行中为32),该值对应于input1中列中的一个范围,以及列中的相应值2:在这种情况下B100002

我想生成一个文件,其中包含相对于范围起点的位置,文件input1的第2列中的每个值

例如,358-344 + 1 = 15是B100043的相对位置值

INPUT1:

Scaffold_1      B100002        1       78
Scaffold_1      B100041        179     243
Scaffold_1      B100043        344     418
Scaffold_1      B100045        519     583
Scaffold_1      B100058        684     751
Scaffold_1      B100059        852     915
Scaffold_1      B100066        1016    1079
Scaffold_1      B100080        1180    1246
Scaffold_1      B100111        1347    1413
Scaffold_1      B100118        1514    1585
Scaffold_2      B123465        31531   31595

输入2:

Scaffold_1      32
Scaffold_1      358
Scaffold_2      31533

必需输出:

B100002      32
B100043      15
B123465      2

这是我的解决方案

  1. 将格式从input1更改为input_1input2更改为input_2(标签分隔)

  2. 使用软件bedtools和awk生成我想要的输出文件。

  3. INPUT_1:

    Scaffold_1      .       B100002        1       78      .      .       .       .
    Scaffold_1      .       B100041        179     243     .      .       .       .
    Scaffold_1      .       B100043        344     418     .      .       .       .
    Scaffold_1      .       B100045        519     583     .      .       .       .
    Scaffold_1      .       B100058        684     751     .      .       .       .
    Scaffold_1      .       B100059        852     915     .      .       .       .
    Scaffold_1      .       B100066        1016    1079    .      .       .       .
    Scaffold_1      .       B100080        1180    1246    .      .       .       .
    Scaffold_1      .       B100111        1347    1413    .      .       .       .
    Scaffold_1      .       B100118        1514    1585    .      .       .       .
    Scaffold_1      .       B101068        9218    9290    .      .       .       .
    Scaffold_2      .       B123465        31531   31595   .      .       .       .
    
    input_2:
    Scaffold_1      .       .      31         33       .       .       .       .
    Scaffold_1      .       .      357        359      .       .       .       .
    Scaffold_2      .       .      31532      31534    .       .       .       .
    
    
    bedtools intersect -wb -a test2 -b test1 | awk '{print $12,($5-$13)}'
    B100002 32
    B100043 15
    B123465 3
    

    如何使用awkperl来实现我的目的? (当我使用bedtools时,我必须更改文件格式。)

2 个答案:

答案 0 :(得分:6)

如果数据文件大小不大,则有一种更简单的方法

$ join input1 input2 | awk '$5<$4 && $3<$5 {print $2, $5-$3+1}'

B100002 32
B100043 15
B123465 3

答案 1 :(得分:0)

这个Perl代码似乎可以解决您的问题

这是一个常见的习惯用法:将input1.txt中的整个字典加载到内存数据结构中 - 这里%data,由脚手架ID索引 - 然后处理对象数据从字典中收集信息

假设您的input1不是很大,这应该可以正常工作。在一个范围内键入数据结构是不可能的,因此必须检查每个候选范围以查看索引是否高于开始和低于结尾

如果匹配,则打印ID与算术结果一起计算基于1的相对索引

请注意,条目Scaffold_2 31533的所需结果应为3而不是2

use strict;
use warnings 'all';
use autodie;

use Data::Dump;

my %data;
{
    open my $fh, '<', 'input1.txt';

    while ( <$fh> ) {
        next unless /\S/;
        my ($scaff, $code, $start, $end) = split;
        push @{ $data{$scaff} }, { start => $start, end => $end, code => $code };
    }
}

open my $fh, '<', 'input2.txt';

while ( <$fh> ) {

    my ($scaff, $index) = split;
    my $items = $data{$scaff} or die qq{No such scaffold "$scaff"};

    for my $item( @$items ) {

        next unless $index >= $item->{start} and $index <= $item->{end};

        printf "%s\t%d\n",
                $item->{code},
                $index - $item->{start} + 1;

        last
    }
}

输出

B100002 32
B100043 15
B123465 3