删除第一次和最后一次出现列值的行

Removing lines with the first and the last occurence of a column value

我有以下文件

    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

在 awk 中你可以试试这个

awk 'NR==1
     {last[NR%3]=;lastLine[NR%3]=[=10=];}
     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 简单打印第一行。
2. {last[NR%3]=;lastLine[NR%3]=[=12=];}将最后两行和当前行存储在一个数组中(lastLine)。
3. 通过 last[(NR-1)%3]==last[(NR-2)%3] && last[(NR-1)%3]==last[NR%3] 我们检查最后一行在第三列中是否与当前行具有相同的值,倒数第二行是否与最后一行具有相同的值(即,它们在第三列中是否具有相同的值)。在这种情况下,我们打印最后一行。

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

$ awk '==p;{p=}' file1 | tac | awk '==p;{p=}' | 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

另一个更简单的 awk 是:

awk 'NR == 1; prev !=  {prev = ; line = 0; next} 
{if (line) print line; line = [=10=]}' 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 和多次通过。

这可能对你有用 (GNU sed):

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

无条件打印第一行(header 行)。一次读取两行,如果这两行没有相同的第三列,则将它们都删除。否则打印第一行并附加下一行并重复。