有两个输入文件,如下面的行所示。
input1
中的第3列和第4列包含范围(例如第一行中的1
至78
)
input2
中的第2列包含单个位置值(第一行中为32
),该值对应于input1
中列中的一个范围,以及列中的相应值2:在这种情况下B100002
。
我想生成一个文件,其中包含相对于范围起点的位置,文件input1
的第2列中的每个值
例如,358-344 + 1 = 15是B100043
的相对位置值
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
Scaffold_1 32
Scaffold_1 358
Scaffold_2 31533
B100002 32
B100043 15
B123465 2
将格式从input1
更改为input_1
和input2
更改为input_2
(标签分隔)
使用软件bedtools和awk生成我想要的输出文件。
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
如何使用awk
或perl
来实现我的目的? (当我使用bedtools时,我必须更改文件格式。)
答案 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