我有一个 ca 的文件。我需要根据第 2 列和第 3 列(范围的开始和结束)中的值提取 17000 行:
文件_1.txt
NC_018723.3 88839 102219
NC_018723.3 156206 160651
NC_018723.3 160885 165615
NC_018723.3 178410 191119
NC_018723.3 226179 242932
NC_018723.3 243929 310071
NC_018723.3 384020 413475
我有第二个文件,也有范围:
文件_2.txt
8410001 8420000
8420001 8430000
28550001 28560000
28560001 28570000
111910001 111920000
111920001 111930000
209310001 209320000
209320001 209330000
209330001 209340000
我正在寻找一种方法来从 file_1.txt 中提取第 2 列和第 3 列的范围落在 file_2.txt 的范围内的行。
任何想法,将不胜感激。
答案1
TXR 口齿不清解决方案。
首先,file_1.txt
增加了一些实际上属于以下范围的范围案例file_2.txt
:
NC_018723.3 88839 102219
NC_018723.3 156206 160651
NC_018723.3 160885 165615
NC_018723.3 178410 191119
NC_018723.3 226179 242932
NC_018723.3 243929 310071
NC_018723.3 384020 413475
FOO_1 8420001 8430000
FOO_2 8430000 8440000
FOO_3 8430000 8440000
FOO_4 209310001 209320001
FOO_5 209310001 209320000
FOO_6 209310002 209320000
FOO_7 209310002 209319999
跑步:
$ txr soln.tl
FOO_1 8420001 8430000
FOO_5 209310001 209320000
FOO_6 209310002 209320000
FOO_7 209310002 209319999
代码在soln.tl
:
(defvarl rtree [tree nil to])
(defun add-range (tree range)
(tree-insert tree range))
(defun lookup-range (tree range)
(let* ((iter (tree-begin tree (from range)))
(node (tree-next iter))
(found (if node (key node))))
(if (and found
(>= (from range) (from found))
(<= (to range) (to found)))
found)))
(awk
(:inputs "file_2.txt")
(t (fconv i i) (add-range rtree [f 0]..[f 1])))
(awk
(:inputs "file_1.txt")
(t (fconv - i i)
(if (lookup-range rtree [f 1]..[f 2])
(prn))))
这里的方法是使用二叉搜索树来存储 的范围file_2.txt
。
TXR Lisp 有一个范围类型:一种带有访问器from
和 的二进制单元to
。我们可以在 REPL 中探索这个:
1> 10..20
#R(10 20)
2> (typeof *1)
range
3> (from *1)
10
4> (to *1)
20
在soln.tl
程序中,表达式[tree nil to]
构造了一个新的二叉搜索树。使其nil
变空,并且to
是关键功能。请注意,它是访问to
范围字段的函数。我们将把范围对象放入这棵树中,并且它们将在其to
字段上设置键控。
函数lookup-range
是最复杂的。给定一个输入范围,它确定该范围是否包含在树中存储的范围内。它用于tree-begin
开始按顺序遍历树,但忽略所有键(即to
字段)低于from
输入范围字段的节点。换句话说,我们正在寻找具有最低to
字段的节点,该字段大于from
我们的搜索范围的字段。
一旦找到该节点,我们就应用简单的重叠测试来确认它。
函数定义之后有两个(awk ..)
表达式。第一个awk
进程file_2.txt
填充树哈希。 Awkfconv
运算符用于将字段转换为整数,并[f 0]..[f 1]
从中构造一个范围对象。
第二个{awk ...)
作业处理file_1.txt
,对范围进行查找,打印那些匹配的记录。
因为平衡二叉树用于范围,所以file_2.txt
可能很大。
输出中不会保留空格,因为我们用 修改了字段fconv
。在 Awk 中,当您分配给字段时,它会通过使用输出字段分隔符连接字段来重新计算记录图像。
为了保留空白,我们可以awk
像这样更改第二个。我们引入一个局部变量并使用它来保存记录recsave
的值(就像在经典 Awk 中一样)。rec
$0
(awk
(:inputs "file_1.txt")
(:let recsave)
(t (set recsave rec)
(fconv - i i)
(if (lookup-range rtree [f 1]..[f 2])
(prn recsave))))