删除具有列值的第一个和最后一个出现的行

时间:2016-01-27 19:38:17

标签: awk sed find-occurrences

我有以下文件

    ID      Score    Other
    ABR     0.98     NBNMSB
    BCG     0.76     NBNMSB
    CVD     0.6      NBNMSB
    BCG     0.9      VSCVA
    CVD     0.56     VSCVA
    ABR     0.9      VSCVA
    CVD     0.7      BAVSC
    BCG     0.4      BAVSC
    ABR     0.5      BAVSC
    AAC     0.1      BAVSC
    ABR     0.8      NBNMSB
    BCG     0.6      NBNMSB
    CVD     0.3      NBNMSB
    BCG     0.7      VSCVA
    CVD     0.0      VSCVA
    ABR     0.1      VSCVA
    CVD     0.5      BAVSC
    BCG     0.8      BAVSC
    ABR     1.0      BAVSC

我想排除第3列中第一次和最后一次出现的值,这样我得到一个输出:

ID      Score    Other
BCG     0.76     NBNMSB
CVD     0.56     VSCVA
BCG     0.4      BAVSC
ABR     0.5      BAVSC
BCG     0.6      NBNMSB
CVD     0.0      VSCVA
BCG     0.8      BAVSC

4 个答案:

答案 0 :(得分:4)

在awk中你可以尝试这个

awk 'NR==1
     {last[NR%3]=$3;lastLine[NR%3]=$0;}
     last[(NR-1)%3]==last[(NR-2)%3] && 
           last[(NR-1)%3]==last[NR%3]{print lastLine[(NR-1)%3]}' test

产生预期的输出:

ID      Score    Other
BCG     0.76     NBNMSB
CVD     0.56     VSCVA
BCG     0.4      BAVSC
ABR     0.5      BAVSC
BCG     0.6      NBNMSB
CVD     0.0      VSCVA
BCG     0.8      BAVSC

<强>解释
1. NR == 1 simple打印第一行 2. {last[NR%3]=$3;lastLine[NR%3]=$0;}将最后两行和当前行存储在数组中(lastLine) 3.通过last[(NR-1)%3]==last[(NR-2)%3] && last[(NR-1)%3]==last[NR%3],我们检查最后一行是否在第三列中与当前行具有相同的值,而第二行在最后一行中是否具有相同的值(即,它们是否在第3列中具有相同的值)。在这种情况下,我们打印最后一行。

答案 1 :(得分:2)

如果您有tac(或gtac),则可以删除第一个实例,反转文件,删除第一个(最后一个)实例并最后一次翻转文件。

$ awk '$3==p;{p=$3}' file1 | tac | awk '$3==p;{p=$3}' | tac
BCG     0.76     NBNMSB
CVD     0.56     VSCVA
BCG     0.4      BAVSC
ABR     0.5      BAVSC
BCG     0.6      NBNMSB
CVD     0.0      VSCVA
BCG     0.8      BAVSC

修改

这是一个更灵活的版本。只需将c的初始值设置为所需的列:

使用第3列:

 c=3 && awk -v c=$c '$c==p;{p=$c}' file1 | tac | awk -v c=$c '$c==p;{p=$c}' | tac

使用第4栏:

 c=4 && awk -v c=$c '$c==p;{p=$c}' file1 | tac | awk -v c=$c '$c==p;{p=$c}' | tac

答案 2 :(得分:2)

另一个更简单的问题是:

awk 'NR == 1; prev != $3 {prev = $3; line = 0; next} 
{if (line) print line; line = $0}' foo.txt | column -t

你会得到

ID   Score  Other
BCG  0.76   NBNMSB
CVD  0.56   VSCVA
BCG  0.4    BAVSC
ABR  0.5    BAVSC
BCG  0.6    NBNMSB
CVD  0.0    VSCVA
BCG  0.8    BAVSC

这样做是将第3列和行存储在名为prevline的变量中,如果它们不是第一次和最后一次出现,则将它们打印出来。

请注意,这只需要1次传递文件,而不是使用tac和多次传递。

答案 3 :(得分:1)

这可能适合你(GNU sed):

sed -r '1p;$!N;/(\S+)\n.*\1$/!d;P;D' file

打印第一行reqardless(标题行)。一次读两行,如果这两行没有相同的第三列,则删除它们。否则打印第一行并附加下一行并重复。