
A、B 2つのファイルがあります。ファイルAには4つの列と600,000の行があります。ファイルBには4つの列と5000の行があります。例:
ファイル-A:
ENSB1 1 12245 0.53 0.002
ENSB2 1 13400 0.27 0.0003
ENSB3 1 14780 0.13 0.00001
ENSB4 1 15201 0.33 0.9
ENSB5 2 56259 0.70 0.0002
ENSB6 2 57000 0.42 0.00004
ENSB7 2 58200 0.50 0.5
ファイル-B:
1 12000 15000 G1
1 14000 16000 G2
2 56000 59000 G3
File-Bの最初の行を選択したいと思います。次に、ファイルAの列3の値がファイルBの列2と3の値の範囲内にあるように、ファイルAの複数行を識別しようとします。ファイルAの2列もファイルBの2列と3列の値の範囲に属し、ファイルBの1列の値は一致します。 File-Aの複数の行が上記の条件を満たすと予想しています。上記の基準に従って複数の行が識別されると、ファイルAの対応する行のうち5列の最も低い値が選択され、ファイルBの対応する行の新しい列に書き込まれます。 File-Bのすべての行に対してこの手順を繰り返します。
予想される新しいファイル:
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
私はLinuxコマンドを初めて学ぶ人ですが、誰でも助けていただければと思います。
答え1
努力する
awk 'NR==FNR {Line[FNR] = $0 # first file processing
Cat[FNR] = $1
Min[FNR] = $2
Max[FNR] = $3
Low[FNR] = 1E10 # initialize to high number so first value from file2 will be lower
ML = FNR
next
}
# second file processing; if same Category and $3 between Min and Max, and $5 lower than before one, keep $5
{for (i=1; i<=ML; i++) if ($2 == Cat[i] &&
$3 >= Min[i] &&
$3 <= Max[i] &&
$5 < Low[i]) Low[i] = $5
}
END {for (i=1; i<=ML; i++) print Line[i], Low[i]
}
' File-B File-A
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
多くの説明は必要ありません。最初のファイル(NR == FNR
)から始めて、カテゴリと範囲/境界の値を維持し、最初の読み取りの実際の値が低くなるようにLow配列要素を設定します。 2番目のファイルを処理するときは、上記のデータセットを繰り返します。新しく読み取ったレコードがアイテムと同じカテゴリを持ち、$ 3がMinとMaxの間にあり、$ 5が以前に取得したレコードよりも低い場合は、$ 5を配列に保持しますLow
。このEND
セクションでは、記録された行と得られたLow
値を標準出力として印刷します。
答え2
anyawk
とanyを使用してくださいsort
。
$ cat tst.sh
#!/usr/bin/env bash
sort -k5,5n -- "$1" |
awk '
NR==FNR {
if ( !($3 in map) ) {
keys[++numKeys] = $3
map[$3] = $5
}
next
}
{
for ( k=1; k<=numKeys; k++ ) {
key = keys[k]
if ( ($2 <= key) && (key <= $3) ) {
print $0, map[key]
next
}
}
}
' - "$2"
$ ./tst.sh 'File-A' 'File-B'
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
重複した$3値がある場合、上記は関連する最低$5を正しく使用しますFile-A
。