列5以降の列数に基づいてファイル行(たとえば、以下のfile.txt)をフィルタリングしたいと思います=0.00000000
。
以下のI / Oは例を示しています。値が0の2つ以上の列(列5以降)を持つ行をフィルタリングします。または=0.00000000
(つまり、値が0の列が2つ以上ある行を削除するか、値が0以外の列が6つ未満(列5以降)の行を削除します。)
1つ、2つ、または3つ以上の列(5列目以降)を持つ行をフィルタリングすることを決定できるように、この操作を柔軟に実行する方法はありますか?=0.00000000
実際のファイルには数千の行と61または71の列がありますが、最初の5つの列は同じです。
ファイル.txt
MT 227 1 1.000 42.0 1:2=0.00036000 1:3=0.00000000 1:4=0.00004200 1:5=0.04300000 1:6=0.03400000 1:7=0.00000000 1:8=0.01204819
MT 233 1 1.000 60.0 1:2=0.10000000 1:3=0.00639386 1:4=0.00000000 1:5=0.00584795 1:6=0.20040000 1:7=0.10030000 1:8=0.02300000
MT 245 1 1.000 107.0 1:2=0.02000000 1:3=0.05600000 1:4=0.00000000 1:5=0.00000000 1:6=0.00000000 1:7=0.02922158 1:8=0.12631579
MT 251 1 1.000 136.0 1:2=0.13384412 1:3=0.01738004 1:4=0.10528891 1:5=0.00070562 1:6=0.01081160 1:7=0.00697347 1:8=0.00453430
MT 264 1 1.000 207.0 1:2=0.00000000 1:3=0.00000000 1:4=0.00000000 1:5=0.00413223 1:6=0.00000000 1:7=0.00192377 1:8=0.00000000
MT 286 1 1.000 300.0 1:2=0.00157816 1:3=0.00126087 1:4=0.00124224 1:5=0.00144928 1:6=0.00209524 1:7=0.00124224 1:8=0.00197719
MT 292 1 1.000 337.0 1:2=0.02000000 1:3=0.30000000 1:4=0.04000000 1:5=0.00050000 1:6=0.00148588 1:7=0.00000000 1:8=0.04000000
MT 293 1 1.000 326.0 1:2=0.00000000 1:3=0.00000000 1:4=0.00000000 1:5=0.00000000 1:6=0.00153610 1:7=0.00113162 1:8=0.00000000
MT 295 1 1.000 333.0 1:2=0.00084409 1:3=0.00125321 1:4=0.00117912 1:5=0.00067806 1:6=0.00041798 1:7=0.00108578 1:8=0.00183284
MT 296 1 1.000 343.0 1:2=0.00000000 1:3=0.00000000 1:4=0.00000000 1:5=0.00233645 1:6=0.00000000 1:7=0.00108070 1:8=0.00144300
出力.txt
MT 233 1 1.000 60.0 1:2=0.10000000 1:3=0.00639386 1:4=0.00000000 1:5=0.00584795 1:6=0.20040000 1:7=0.10030000 1:8=0.02300000
MT 251 1 1.000 136.0 1:2=0.13384412 1:3=0.01738004 1:4=0.10528891 1:5=0.00070562 1:6=0.01081160 1:7=0.00697347 1:8=0.00453430
MT 286 1 1.000 300.0 1:2=0.00157816 1:3=0.00126087 1:4=0.00124224 1:5=0.00144928 1:6=0.00209524 1:7=0.00124224 1:8=0.00197719
MT 292 1 1.000 337.0 1:2=0.02000000 1:3=0.30000000 1:4=0.04000000 1:5=0.00050000 1:6=0.00148588 1:7=0.00000000 1:8=0.04000000
MT 295 1 1.000 333.0 1:2=0.00084409 1:3=0.00125321 1:4=0.00117912 1:5=0.00067806 1:6=0.00041798 1:7=0.00108578 1:8=0.00183284
=0.00000000
列を使用して(列5以降)行を削除する方がはるかに簡単になる可能性がありますが、これを行うと、あまりにもgrep -v "=0.00000000"
多くのデータが失われます。どんな助けでも大変感謝します!
答え1
私が見つけることができる最も簡単な解決策は次のとおりです(はい、非常に簡単です)。
awk -F '=0\\.00000000' 'NF<=2' file
これにはいくつかの解決策があります。
grep
テキストを見つけるのは非常に速く、正しい正規表現だけで済みます。grep -vE '^([^ ]* ){5}.*(=0\.00000000.*){2}' file
- この部分は、
^([^ ]* ){5}
行()の先頭から始まり、スペース(5()個)で{5}
区切られた列(スペースではない)と一致します^
。 - その後、
.*(=0\.00000000.*){2}
その行で少なくとも2つが一致します=0\.00000000
。 - 最後に、一致を反転し(
-v
)拡張(ERE)正規表現(あまり\
必要ありません)を使用します。
- この部分は、
0
一致する数を厳密に制限します。
Sedにも同様の正規表現があります。
sed '/^\([^ ]* \)\{5\}.*\(=0\.00000000.*\)\{2\}/d' file
ただし、パターンと一致しない行は印刷されます(簡単に失敗する可能性があります)。
または
awkはこの行をテキストとして扱います。
awk -F '=0\\.00000000' 'NF<=2' file
awkは浮動小数点数を解析し、
0
値を確認できます。@GlennJackmanの答えを使用してください。
答え2
スペースまたは=
フィールド区切り文字を使用して、列7から始めて0の値を計算します。複数の値がある場合は次の行に進み、そうでない場合はその行を印刷します。
awk -F '[= ]+' '{
z = 0
for (c = 7; c <= NF; c += 2)
if ($c == 0.0 && ++z > 1)
next
print
}' file
答え3
これは、この文字列の複数のインスタンスを含まない行を印刷する最も簡単な方法です。
grep -v '=0\.00000000.*0\.00000000' file.txt
ファイルは列5の後にのみ表示され、一度だけ表示されるかまったく表示されない行のみを印刷しようとするため、上記のコードは複数回表示されない行を印刷します。このパターンは、どの列に表示されるかに関係なく、1行=0\.00000000.*0\.00000000
の2つのインスタンスと一致し、1行のどこにも3行目、4行目、5行目などがある場合、その行は印刷されません。=0.00000000
試行中のコマンドはその文字列のインスタンスを含まない行を印刷するため、不要な2行目は印刷されません。
その文字列のインスタンスが含まれなくなった行を印刷するには、別のインスタンスを追加してください.*0.00000000
。たとえば、3つ以上のインスタンスが含まれていない行を印刷するには、次のようにします。
grep -v '=0\.00000000.*0\.00000000.*0\.00000000' file.txt
これには、文字列の3つのインスタンスを含む3行目が含まれます。