AWK:如果文件1中的列落在其他文件中的两列中声明的范围内,则提取行

时间:2014-05-07 19:02:02

标签: multidimensional-array awk bioinformatics genome

目前我正在努力解决我尚未解决的AWK问题。我有一个巨大的文件(30GB),基因组数据包含一个包含位置的列表(在第1列和第2列中声明)和第二个包含多个范围的列表(在第3列,第4列和第5列中声明)。我想提取第一个文件中位置落在秒文件中声明的范围内的所有行。由于位置在某个染色体(chr)中仅是唯一的,因此如果chr是相同的(即文件1中的col1与file2中的col3匹配),则必须进行测试。

档案1

chromosome position another....hundred.....columns
chr1       816 .....
chr1       991 .....
chr2       816 .....
chr2       880 .....
chr2       18768 .....
...
chr22      9736286 .....

文件2

name    identifier chromosome   start    end
GENE1   ucsc.86    chr1         800      900
GENE2   ucsc.45    chr2         700      1700
GENE3   ucsc.46    chr2         18000    19000

预期产出

chromosome position another....hundred.....columns
chr1       816 .....
chr2       816 .....
chr2       880 .....
chr2       18768 .....

我打算做的总结(半编码):

(if $1(in file 1) matches $3(in file 2){            ##test if in the correct chr
   if ($2(in file 1) >= $4 && =< $5 (in file 2){    ##test if pos is in the range
         print $0 (in file 1)                       ##if so print the row from file1
   }
}

我很了解如何通过将file1放在一个数组中并使用position作为索引来理解如何解决这个问题但是我仍然遇到chr的问题,而且file1是一个很大的方法来放入一个数组(虽然我有128GB的RAM)。我已经尝试了一些多维数组但却无法弄清楚如何做到这一点。

非常感谢你的帮助。

2014年8月5日更新 在文件2中添加了第三行,其中包含相同chrom中的另一个范围。就像在第二行。在下面的脚本中跳过此行。

2 个答案:

答案 0 :(得分:5)

它是这样的,未经测试的:

awk '
NR==FNR{ start[$3] = $4; end[$3] = $5; next }
(FNR==1) || ( ($1 in start) && ($2 >= start[$1]) && ($2 <= end[$1]) )
' file2 file1

答案 1 :(得分:2)

数据集的变化实际上大大改变了这个问题。你引入了一个用作密钥的元素,因为密钥必须是唯一的,否则它会被覆盖。

对于您的数据集,最好制作复合键。类似的东西:

awk '
NR==FNR{ range[$3,$4,$5]; next }
FNR==1
{
    for(x in range) {
        split(x, check, SUBSEP); 
        if($1==check[1] && $2>=check[2] && $2<=check[3]) print $0
    }
}    
' file2 file1
chromosome position another....hundred.....columns
chr1       816 .....
chr2       816 .....
chr2       880 .....
chr2       18768