次のファイルがあります
> head map.stats
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
ID=NbD053287.1.mrna1;Name=NbD053287.1;Parent=NbD053287.1.path1;coverage=100.0;identity=94.1;matches=738;mismatches=0;indels=46;unknowns=0
ID=NbD053281.1.mrna1;Name=NbD053281.1;Parent=NbD053281.1.path1;coverage=99.3;identity=99.1;matches=1476;mismatches=14;indels=0;unknowns=0
$identity >= 95 && $coverage == 100
この出力を得るためにフィルタリングしたいと思います。
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
試してみましたgrep -oP '(?<=identity=).*?(?=;)' map.stats | awk '$1 >= 99'
が、それほど遠くはできませんでした。このフィルタリングはどのように可能ですか?
事前にありがとう
答え1
別のアプローチは次のとおりです。
$ awk -F'[;=]' '$10>=95 && $8 == 100' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
秘密は、フィールド区切り文字を;
またはに設定することです=
(そう-F'[;=]'
します)。すると、 の値はidentity
10 番目のフィールドになり、 の値はcoverage
8 番目のフィールドになります。awk
式がtrueと評価された場合、デフォルトのジョブは現在の行を印刷することであるため、これら2つの条件に一致するすべての行が印刷されることを意味します$10>=95 && $8 == 100
。
実際にはGNUでもこれを行うことができますが、完全な行が必要であり、振り返る理由がないため、grep
そのオプションは必要ありません。-o
必要なのは範囲を定義するだけです。 ( )95
までの値が必要なので、次の間に数字が必要であることを意味します。100
>=95
9
5
9
100
$ grep -P 'coverage=100.0.*identity=(9[5..9]|100)' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
私は、同一性が100より大きい値を持つことができないと仮定していることに注意してください。これはおそらく配列の保存を見ており、100%同じものよりも同様の結果が得られないため、安全な仮定のようです。
答え2
まず、次のようにフィールドを数値に変換してみましょう。
awk -F= 'NR==1 { for(i=1;i<=NF;i++) printf "%2d %s\n",i,$i ;}' file
1 ID
2 NbD053289.1.mrna1;Name
3 NbD053289.1;Parent
4 NbD053289.1.path1;coverage
5 100.0;identity
6 100.0;matches
7 702;mismatches
8 0;indels
9 0;unknowns
10 0
したがって、Coverageは5、Identityは6です。
==
次に、awkは文字列と一致するため、直接使用できないため、+1を使用して数値に変換します。
この出力
awk -F= '$6+1>96 && ($5+1) == 101' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
どこ
-F=
=
awkに区切り文字として使用するように指示する$6+1>96
上記のように数値に変換してフィルタリングします。