我有2个文件;让我们称它们为file1和file2。 file1包含每行中的开始和结束坐标,例如:
start end
2000 2696
3465 3688
8904 9546
等
file2有几列,其中第一列与问题最相关:
position v2 v3 v4
3546 value12 value13 value14
9847 value22 value23 value24
12000 value32 value33 value34
现在,我需要输出一个新文件,该文件只包含file2的行,其中'position'值(第1列)位于任何列的'start'和'end'值之间of file1。在R我只做一个双循环,但它需要太多时间(文件很大),所以需要在bash中进行。如果问题不清楚,可以使用R循环:
for(i in 1:dim(file1)[1]){
for(j in 1:dim(file2)[1]){
if(file2[j,1]>file1$start[i] & file2[j,1]<file1$end[i]) file2$select=1 else file2$select=0
}
}
非常确定有一种简单的方法可以使用bash / awk ...
答案 0 :(得分:2)
awk看起来像这样,但你需要先从file1和file2中删除第一行:
awk 'FNR==NR{x[i]=$1;y[i++]=$2;next}{for(j=0;j<i;j++){if($1>=x[j]&&$1<=y[j]){print $0}}}' file1 file2
“FNR == NR”之后的花括号中的位仅适用于file1的处理,它表示将field1存储在数组x []和field2中的数组y []中,因此我们有每个的上限和下限范围。第二组花括号中的位仅适用于处理file2。它表示迭代数组x []和y []中的所有边界,并查看field1是否在边界之间,如果是,则打印整个reocrd。
如果你不想在开始时删除标题行,你可以使awk更复杂一点,并忽略它:
awk 'FNR==1{next}FNR==NR{x[i]=$1;y[i++]=$2;next}{for(j=0;j<i;j++){if($1>=x[j]&&$1<=y[j]){print $0}}}' file1 file2
<强> EDITED 强>
好的,我添加了代码来检查“染色体”(无论是什么!),假设它位于两个文件的第一个字段中,如下所示:
File1中
x 2000 2696
x 3465 3688
x 8904 9546
文件2
x 3546 value12 value13 value14
y 3467 value12 value13 value14
x 9847 value22 value23 value24
x 12000 value32 value33 value34
因此,代码现在也将染色体存储在数组c []中,并在输出之前检查它们是否相等。
awk 'BEGIN{i=0}FNR==NR{c[i]=$1;x[i]=$2;y[i++]=$3;next}{for(j=0;j<i;j++){if(c[j]==$1&&$2>=x[j]&&$2<=y[j]){print $0;next}}}' file1 file2
答案 1 :(得分:0)
不知道如何在bash中执行此操作...
我会尝试一个perl脚本,读取第一个文件并将其存储在内存中(如果可能,它取决于它的大小)然后逐行浏览第二个文件并进行比较以输出行或不
我认为你也可以在R中做到这一点......同样的方法:存储第一个文件,循环第二个文件的每一行。
此外,如果间隔不重叠,您可以对文件进行排序以加快算法速度。
答案 2 :(得分:0)
这应该比for
循环
res <- apply(file2, 1, function(row)
{
any(row$position > file1$start & row$position < file1$end)
})
答案 3 :(得分:0)
假设文件的分隔符是空格(如果不是 - 更改-d estting)。
该脚本使用cut
来提取file2的第一个字段。
然后一个简单的grep搜索file1中的字段。如果存在,则打印file2中的行。
#!/bin/bash
while read line
do
word=$(echo $line | cut -f1 -d" ")
grep -c $word file1 >/dev/null
if [ $? -eq 0 ];then
echo "$line"
fi
done < file2