Bash - 过滤占据一定比例列的行

Bash - 过滤占据一定比例列的行

因此,我有大量文件,每个文件有 8 列和很多行。这是其中一个的头部示例。

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 列的行都带有“-”,有效。

我曾经能够使用一个简单的 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 列,如果该列的值等于-它与 相加的值count,如果count一行的值大于 1,则不会打印。

答案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

相关内容