根据属于第二个文件范围内的列打印文件中的行子集

根据属于第二个文件范围内的列打印文件中的行子集

我有一个包含 4 列 ( ) 的文件file1.txt

chr1    1156    G       G
chr1    1157    A       A
chr1    1165    T       T
chr1    1173    C       C
chr1    1175    G       G
chr1    1178    T       T
chr1    1181    C       C
chr1    1186    G       G

第二个文件 ( file2.txt) 包含范围、2 列:

1100    1160
1170    1180

我想从中提取file1第 2 列属于 范围内的行file2。上述示例所需的输出为:

chr1    1156    G       G
chr1    1157    A       A
chr1    1173    C       C
chr1    1175    G       G
chr1    1178    T       T

基于我尝试过的类似帖子,但它没有产生输出:

awk 'NR==FNR{ range[$1,$2]; next }{for(x in range) {split(x, check, SUBSEP); if($2>=check[1] && $2<=check[2]) print}} ' file2.txt file1.txt > output.txt

我也尝试了以下方法,并取得了同样的运气:

awk 'NR == FNR {ref[$1][$2]} if ($1 <= key && key <= $2) sum += ref[$2][key] print $0, sum} file2.txt file1.txt > output.txt

如果有人有任何建议,我们将不胜感激。

答案1

以下awk程序应该执行以下操作:

awk 'NR==FNR{rng++;start[rng]=$1;end[rng]=$2;next}
     {for (i=1;i<=rng;i++) if (($2>=start[i])&&($2<=end[i])) {print; next}}' file2.txt file1.txt

其工作原理如下:

  • 在解析第一个输入文件 ( ) 时(由全局行计数器file2.txt表示,等于每个文件行计数器),我们将范围开始和结束编号注册在两个数组中,并且(同时计算一个数组中的范围数)柜台)。之后,我们立即跳到下一行执行。NRFNRstartendrng
  • 在处理file1.txt(NR现在大于FNR) 时,我们检查每一行的第 2 列是否分别落在startend数组中相应条目指定的任何范围内。如果是这样,我们打印当前行并再次跳到下一行执行。

答案2

这两个文件都有数千行长。

因此,对于过去 30 年的任何计算机来说,几千行实际上根本不算什么数据。效率对你来说并不重要。 (粗略计算:第一个文件每行 32 个字节,第二个文件每行 16 个字节,所以每行总共 48 个字节,假设你的计算机可以腾出 2 GB RAM,甚至稍微脸红之前,你可以将 4400 万行读入 RAM无需担心。)

因为这看起来像基因组学/生物信息学,所以我认为无论如何,你迟早有很大机会接触到Python。

#!/usr/bin/env python3
file1 = open("file1.txt", "r", encoding="ascii")
file2 = open("file2.txt", "r", encoding="ascii")

lines1 = file1.readlines()
lines2 = file2.readlines()

file1.close()
file2.close()

for dataline, rangeline in zip(lines1, lines2):
  splitrange = rangeline.split()
  lower = int(splitrange[0])
  upper = int(splitrange[1])
  
  ignore, valuestring, nucleotide1, nucleotide2 = dataline.split()
  value = int(valuestring)
  if lower <= value and value <= upper:
    print(dataline)

就是这样。

它像在中那样简洁吗awk?当然不是。这是尽可能快的吗?不,一点也不(但这并不重要)。你有机会记住这在一周内发生了什么吗?最可能。

如前所述,无论如何,您很可能会做其他与 AWK 设计目的无关的事情,因此 Python 可能是一个自然的工具。几乎可以肯定的是,学习生物蟒蛇是个好主意。

答案3

使用两次调用awk

<file2.txt awk '{ print "$2 >= " $1 " && $2 <= " $2 }' |
           awk -f - file1.txt

答案4

cat file2 |while read line ; do col1=$(echo $line| awk '{print $1}'); col2=$(echo $line | awk '{print $2}'); cat file1|while read fine; do echo $fine |awk -v col1="$col1" -v col2="$col2" '$2 >=col1 && $2 <col2'; done; done

输出

chr1    1156    G       G
chr1    1157    A       A
chr1    1173    C       C
chr1    1175    G       G
chr1    1178    T       T

相关内容