
対立遺伝子の頻度を記述するファイルがあり、最後の2列の頻度の1つが0.01以上の場合は、awkを使用して行を印刷しようとします。周波数ファイルの形式は次のとおりです。私は最後の2つの周波数に興味があります。
2L 10000133 A 125/125 115/131 0/125 16/131
2L 10000374 A 121/124 143/143 3/124 0/143
awkに関する限られた知識に基づいて、次のコードを書いています。
cat myfile.txt |
awk ' BEGIN { {FS="/"}{OFS="\t"}
if( ($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01"))
{ print $1,$2 }
}' > myfilteredfile.txt
ただし、出力ファイルmyfilteredfile.txtは空です。出力ファイルが印刷される予定です。
2L 10000133
2L 10000374
これは、2行の最後の2列の頻度が0.01以上であるためです。どんな提案がありますか?
答え1
既存のスクリプトには2つの問題があります。
最初は区切り記号です。スペースとスラッシュに分割するには、対応する正規表現を指定し、次のように使用する必要がありますFS
。FS="[ /]+"
2番目は、すべてのコードがBEGIN
ブロック内にあることです。BEGIN
初期化ブロック(または他の場所)に区切り文字が必要です。例えば特定のAWKパラメータを使用)次に、マッチャブロックを使用してその行を処理します。
このバージョンの仕組み:
awk 'BEGIN { FS="[ /]+"; OFS="\t" }
(($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01")) {
print $1, $2
}' myfile.txt
厳密に言えば、数値を一致させようとするので、0.01
代わりに使用する方が良いです。"0.01"
awk 'BEGIN { FS="[ /]+"; OFS="\t" }
(($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01)) {
print $1, $2
}' myfile.txt
答え2
$ awk '{ split($(NF-1),a,/\//) } { split($NF,b,/\//) } a[1]/a[2] > 0.01 || b[1]/b[2] > 0.01 { print $1, $2 }' file.in
2L 10000133
2L 10000374
これにより、最後の2つのフィールドが文字ごとに別々に分割され、/
その部分が2つの配列a
に格納されますb
。除算結果が0.01より大きい数値になると、最初の2つのフィールドが出力されます。
$NF
入力レコード(行)の最後のフィールド(列)値。$(NF-1)
2番目のフィールドの値。
コードの問題は、BEGIN
do everythingブロック内ですべての操作を実行することです。このブロックは主に初期化に使用され、実行されます。今後実際に読み取ったデータはありません。FS
他の回答で指摘した選択値にも問題があります。
また、数字として使用するときに数字を引用する必要はありません。
答え3
In部分awk
はBEGIN{...}
入力から入力行を読み取る前に実行されるため、コードawk
から実際に入力を読み取らないため、何も返しません。餌を与えたい場合はを使用する必要がありますgetline
が、1行だけを読み取るので、for
ループを使用してすべてを読むことができます。
もう1つの問題は、これを使用してFS="/"
行を区切りフィールドに分割する場合ですが、最大フィールドは5つにすぎず、送信されたフィールドは次のようになるため/
問題はありません。$8
125 115
131 0
125 16
このコードを使って欲しいものを得ることができます。また、awk
ファイルから直接読み取ることができるので、そこでcat
使用する必要はありません。
awk -F'[/ ]+' 'BEGIN{ OFS="\t"}
{if( ($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01))
{ print $1,$2 }
}' infile