有没有办法根据阈值使用awk来删除行?

时间:2017-03-11 18:31:46

标签: awk sed

我在第一列中有一堆标识符,并在下一列中为各个样本(对于这些标识符)分数,如下所示;

ID       1         2          3
21       20        70         80
13       44        50         10

我知道awk语法来计算当一行中的每个值小于20 (($2 < 20) && ($3 < 20) && ($4 < 20))时有多少个实例,但我不知道如何过滤它们。

如果我执行(($2 > 20) && ($3 > 20) && ($4 > 20))并打印并保存它们,则它们不一样,因为在第一个示例中您将有一个实例,其中一个值小于20并且仍然保留该行,因为不是所有值小于20(例如10 40 45)。对于>版本,所有值必须大于20,因此该行将被删除。

你能帮帮我吗?也许我需要sed? 谢谢!

3 个答案:

答案 0 :(得分:2)

您可以检查其中一个值是否满足您的条件迭代到NF并根据此打印整行:

awk '{ 
        if (NR != 1){
            remove = 0;
            for (i = 1; i <= NF; i++) {
                if ($i < 20) {
                    remove = 1;
                    break;
                }
            }
            if (remove == 0){
                print $0
            }
        }
    }' test.txt

答案 1 :(得分:2)

在没有提供所需输出的情况下,您所要求的内容并不十分清楚。此外,您的输入文件似乎有一个标题增加混乱。

这是您可以使用的替代方案,注释表示将打印哪些记录。您可以扩展到其他列。

   awk -v t=20 '$2<t && $3<t' file         # all strictly less
   awk -v t=20 '!($2<t && $3<t)' file      # any greater or equal 
   awk -v t=20 '$2<t || $3<t' file         # any strictly less 
   awk -v t=20 '!($2<t || $3<t)' file      # all greater or equal

也许会帮助你理解,这些基本的平等

  !(p && q) == !p || !q    # for logical p,q
  !(p || q) == !p && !q
     !(x<y) == x>=y        # for numerical x,y

答案 2 :(得分:1)

你很可能做错了。语句&#34;你将在第一个例子中有一个实例,其中一个值小于20并且仍然保留该行,因为并非所有值都小于20(例如10 40 45)&#34; 无效。使用&amp;&amp;如果所有条件AND都返回true,则要求输出逻辑AND和链接AND将输出;意思是不保留行:

$ echo "10        40         45" |awk '(($1<20) && ($2<20) && ($3<20))'
#Output : no output

如果你想保持在行之上,那么你需要OR:

$ echo "10        40         45" |awk '(($1<20) || ($2<20) || ($3<20))'
#Output:
10        40         45

同样:

$ echo "10        40         45" |awk '(($1>20) && ($2>20) && ($3>20))'
# Output: No Output
$ echo "10        40         45" |awk '(($1>20) || ($2>20) || ($3>20))'
#Output:
10        40         45