如何从两个文件中提取一定范围的数字?

如何从两个文件中提取一定范围的数字?

我正在尝试从两个文件中提取数字范围。

$cat file1.txt

chr1 69509
chr1 69511
chr1 71000
chr1 358112
chr1 586874
chr1 744200
。 。 。

$cat file2.txt

chr1 69091 70005
chr1 358070 358183
chr1 586842 586955
chr1 744195 744343
。 。 。

期望的输出:

69509 CHR1 69091 70005
69511 CHR1 69091 70005
71000超出范围
358112 CHR1 358070 358183
586874 CHR1 586842 586955
744200

下面是我的 awk 代码。

awk 'NR==FNR{x[$1] = $2; next;}{for (i in x) {if (x[i] > $2 && x[i] < $3)print x[i], $1,$2,$3;else{print x[i], "out of range"}}}' file1.txt file2.txt

但是,此代码返回的输出仅包含最后一个 NR 的数据。

例如,

744200 超出范围
744200 超出范围
744200 超出范围
744200 chr1 744195 744343

我猜这与 NR 和 FNR 有关,但我不知道该怎么做。

答案1

x这是因为您正在键入第一个文件中所有行都$1相同的数组。chr1因此,在每一行上,数组内容都基于相同的键进行索引,并用 中的值覆盖$2。因此,到文件末尾时,数组中就有一个条目x['chr1']=744200

您需要唯一地存储该行。将密钥存储为元组$1 FS $2并将逻辑修改为

awk 'NR == FNR { x[$1 FS $2] = $2; next }{ 
     for (key in x) { 
       split(key, arr)
       if (arr[2] > $2 && arr[2] < $3) 
           print arr[2], $0 
       else {
           print arr[2], "out of range"
       }
     }
}' file1 file2

要改进逻辑以仅对两个文件的第一列相同的行进行范围检查,请向ifas添加一个条件

if ( (arr[2] > $2 && arr[2] < $3) && ( $1 == arr[1] ) ) 

答案2

假设 file2 范围不重叠,如您的示例所示:

$ cat tst.awk
NF==3 { beg=$2; end=$3; all=$0; next }
{ print $2, ( ($2 >= beg) && ($2 <= end) ? all : "out of range" ) }

$ sort -sk2n file2 file1 | awk -f tst.awk
69509 chr1 69091 70005
69511 chr1 69091 70005
71000 out of range
358112 chr1 358070 358183
586874 chr1 586842 586955
744200 chr1 744195 744343

它使用 GNU 排序(“稳定排序”)来确保在相同 s 的情况下-sfile2 条目在该条目之前打印。file1$2

相关内容