打印包含给定数字的行,然后至少按n次制表符

时间:2018-10-08 16:50:25

标签: bash shell grep

我有一个制表符分隔文件:

scaffold_0      102     1       4       0       1       1       1       2       1       2       1       3
scaffold_0      103     1       4       0       2       1       1       2       1       2       1       3
scaffold_0      104     2       4       0       2       3       5       2       1       2       7       3
scaffold_0      105     1       4       0       2       1       1       2       1       2       1       3
scaffold_0      106     1       4       0       2       1       1       2       1       2       1       3
scaffold_0      107     2       3       3       2       5       1       2       1       2       2       4
scaffold_0      108     1       4       0       2       1       1       2       1       2       2       5
scaffold_0      109     1       4       0       2       1       1       2       1       2       2       5
scaffold_0      110     1       3       0       2       1       1       2       1       2       2       5
scaffold_0      111     1       3       0       2       1       1       1       1       2       2       5

,并且需要抓住9或更多列中显示等于或大于2的行。 这样就可以了:

scaffold_0      104     2       4       0       2       3       5       2       1       2       7       3
scaffold_0      107     2       3       3       2       5       1       2       1       2       2       4

另一种放置方式是,我必须删除每行大于2的0和1s计数的行。

我尝试过:

grep '[2-9]\t{9,}'

它不起作用,即使这样做也不会抓住10、11、101等。

(抓住2、12、22等应该不是问题)

3 个答案:

答案 0 :(得分:3)

$ awk '{c=0; for (i=2;i<=NF;i++) c+=($i>=2)} c>8' file
scaffold_0      104     2       4       0       2       3       5       2       1       2       7       3
scaffold_0      107     2       3       3       2       5       1       2       1       2       2       4

它可以在任何UNIX机器上的任何外壳中工作,并且运行速度比当前接受的答案快几个数量级。

答案 1 :(得分:1)

while IFS= read -r line; do
    count=$(
        <<<"$line" cut -f2- | 
        tr '\t' '\n' | 
        grep -x '0\|1' | 
        wc -l
    )
    if (( count <= 2 )); then
        echo "$line"
    fi
done <file

对于每一行,从文件的第二行开始获取所有字段,然后用制表符代替换行符,仅过滤零或一的行,然后计算行数。如果计数小于或等于2,则打印该行。

  1. 我使用零和1,因为我认为它将更快(wc -l计数的行更少,grep打印的行更少),但是您可以轻松地grep -v -x '0\|1' | wc -l(( count > 9 ))
  2. 我觉得有人会发布更好的awk解决方案,但是我不知道awk这么写我自己。
  3. 这不适用于负数。

tutorialspoint上的实时示例。

答案 2 :(得分:1)

使用numgrep

while read x ; do 
    numgrep -l '/2../' <<< "$x" | { [ $(wc -l) -ge 9 ] && echo "$x" ; } ; 
done < file

输出:

scaffold_0      104     2       4       0       2       3       5       2       1       2       7       3
scaffold_0      107     2       3       3       2       5       1       2       1       2       2       4

请注意:numgrep和此代码将可同时使用负数和小数。