両方のファイルから数値範囲を抽出するには?

両方のファイルから数値範囲を抽出するには?

両方のファイルから数値範囲を抽出しようとしています。

$cat ファイル1.txt

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

$cat ファイル2.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
5469

以下は私の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

両方のファイルの最初の列が同じ行でのみスコープチェックを実行するようにロジックを改善するには、if次の条件を追加します。

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が指定された-sこの項目の前にfile2項目を印刷するようにします。file1$2

関連情報