比较单个文件中的多个列,计算这些列中值的出现次数

时间:2016-04-21 14:02:44

标签: perl awk sed grep

我有一个包含21列的文件;

Name    Grade1    Grade2   Grade3   Grade4   Grade5  .... Grade20
Zoe       60        70      NA       NA        NA            67

现在,我想只保留超过5等级NA的名字。 有些名称包含NA。

我知道awk可以胜任这项工作。但我不确定如何比较所有列而不必单独比较它们。

我试过了:

    more input_file.txt | awk 'total = count20[$2,$3,$4,$5,$6,$7,$8,$9,$10,
    $11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21]++, if (($2 == "NA" || $3 == "NA" || 
    $4 == "NA" || $5 == "NA" || $6 == "NA" || $7 == "NA" || $8 == "NA" || $9 == "NA" 
    || $10 == "NA" || $11 == "NA" || $12 == "NA" || $13 == "NA" || $14 == "NA" || 
    $15 == "NA" || $16 == "NA" || $17 == "NA" || $18 == "NA" || $19 == "NA" || 
    $20 == "NA" || $21 == "NA") && total > 4) { print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"
    $6"\t"$7"\t"$8"\t"$9"\t"$10"\t"$11"\t"$12"\t"$13"\t"$14"\t"$15"\t"$16"\t"$17"\t"
    $18"\t"$19"\t"$20"\t"$21 }' > test.txt

它不起作用,我不确定为什么或如何更有效地做到这一点。

编辑:更准确地说,想要的输出是一个包含名称的文件,以及包含NA的列数超过5列的学生的所有列。

6 个答案:

答案 0 :(得分:1)

awk救援!

$ awk -F'NA' 'NF>5'

假设您的名称列不包含NA作为子字符串。使用NA作为字段分隔符并计算字段,如果有超过5个字段表示至少有5个NA,则默认操作是打印该行,因此无需指定。这将为您提供5个或更多NA的记录,如果您想要严格超过5,则将阈值更改为6.

答案 1 :(得分:1)

此命令至少打印六次包含NA的所有行:

grep -E '(NA.*){6}' infile

如果学生的姓名也包含NA,则可能会被绊倒。要解决此问题,您可以使用

grep -E '^[^[:blank:]]+[[:blank:]]+(NA.*){6,}' infile

在第一列之后仅计算NA

答案 2 :(得分:0)

这是使用awk执行此操作的一种相当基本的方法:

awk '{ count = 0; for (i = 2; i <= NF; ++i) if ($i == "NA") ++count } count > 5' file

循环遍历每个字段并检查它是否等于&#34; NA&#34;。如果是这样,它会增加该记录的总计数。当计数大于5时,将打印记录。

答案 3 :(得分:0)

它标记为perl所以perl回答:

perl -ne 'print if (grep /^NA$/, split ) > 5'

其中:

  • 逐行迭代
  • 做空白分割
  • greps NA
  • 的字段 如果计数为> 5 ,则
  • 打印

答案 4 :(得分:0)

使用GNU awk进行单词边界:

awk -F'\\<NA\\>' 'NF>6'

如果您的字段按标签分隔,则使用任何awk:

awk -F'\tNA(\t|$)' 'NF>6'

任何POSIX awk表示字段之间的任何类型的空格:

awk -F'[[:space:]]NA([[:space:]]|$)' 'NF>6'

答案 5 :(得分:0)

在Perl中,只计算等于NA

的字段数
perl -ne 'print if 5 <= grep { $_ eq "NA" } split' test.txt
或者,正如Tom Fenech在评论中指出的那样

perl -ane 'print if 5 <= grep { $_ eq "NA" } @F' test.txt