Bash - 特定の割合の列を占める行フィルタリング

Bash - 特定の割合の列を占める行フィルタリング

だから私はそれぞれ8つの列と多くの行を持つ多数のファイルを持っています。以下は、そのうちの1つの頭の例です。

ID       Ct       1          2          3          4           5             6
1        0        consensus  -          -          -           -             -
2        0        consensus  -          -          -           -             -
3        0        consensus  consensus  consensus  consensus   consensus     consensus
4        0        consensus  -          consensus  -           -             -
5        0        -          AT         AT         GC          GC            AT
6        0        consensus  -          -          -           consensus     -
7        0        consensus  -          -          -           -             -
8        0        consensus  consensus  consensus  -           consensus     consensus
9        0        consensus  -          -          -           -             -

最後の6つの列が少なくとも5/6以上を占めるすべての行を分離したいと思います。したがって、ID 3、5、8(4、6、9行)は私の頭からのものです。したがって、2つ未満の列を持つすべての行に "-"を有効にしたいと思います。

私はプログラムが2番目の列でどのくらいの列を占めたかを計算したので、単純なawkスクリプトを使用してこれを行うことができました。これ以上これを行うことができないようです。最良のアプローチは何ですか?

答え1

どのくらい行くのでしょうか?

awk 'gsub(/-/, "&") < 2' file
ID       Ct       1          2          3          4           5             6
3        0        consensus  consensus  consensus  consensus   consensus     consensus
5        0        -          AT         AT         GC          GC            AT
8        0        consensus  consensus  consensus  -           consensus     consensus

わかりますか? rgは何も言いません。目的の出力 - 単一の出力ファイル、出力行の前にファイル名を付けること、元のファイルと同じ名前の新しいファイル、または何をしたいですか?

編集する(新しいファイル名にコメントを付けた後):

awk 'gsub(/-/, "&") < 2 {print > (FILENAME ".new")}' /path/to/file/*

答え2

すべてのファイルが同じディレクトリにある場合は、forループ/globを使用して各ファイルを繰り返し、そのファイルに対してawkコマンドを実行できます。

for file in /path/to/files/*; do
    awk '{
        count=0
        for (i=3;i<=8;i++) {
            if ($i == "-") {
                count++
            }
        }
        if ((count <= 1)) {
            print
        }
    }' "$file"
done

各行に対して列3〜8を繰り返し、その列の値が追加さ-れた値と等しい場合、行の値が1より大きい場合は印刷されません。countcount

答え3

Perlはこの種の作業に便利です。具体的grepには、明示的なループなしでフィールドごとに操作を実行でき、その結果(スカラーコンテキストで評価したとき)の一致数が得られます。例えば

$ perl -lane 'print if 3 > grep { $_ eq "-" } splice @F, 2' file
ID       Ct       1          2          3          4           5             6
3        0        consensus  consensus  consensus  consensus   consensus     consensus
5        0        -          AT         AT         GC          GC            AT
8        0        consensus  consensus  consensus  -           consensus     consensus

関連情報