両方のファイルから数値範囲を抽出しようとしています。
$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