删除大文件中前几列相同的第二行

删除大文件中前几列相同的第二行

我有一个看起来像这样的文件:

A 1 abc
A 1 def
A 2 ttt
B 2 ppp
B 2 qqq

当前两个键相同时,我想保留第一行,所以像这样:

A 1 abc
A 2 ttt
B 2 ppp

我找到了一个上一个问题这解决了这个问题。但是,我的文件大小为 1.2 GB,并且我匹配前 19 列。所以当我运行这个时:

  awk  '!array[$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19]++' infile > outfile

我明白了:

cmd. line:2: (FILENAME=infile FNR=287807) fatal: dupnode: r->stptr: can't allocate memory (Not enough memory)

显然我无法分解文件来处理,因为我不知道重复项在哪里。我愿意用速度换取内存来解决这个问题。 (该文件大约有160万行)。

答案1

由于您的文件似乎已排序:

sort -m -u -k 1,2 < file

-m为了合并不会尝试对文件进行排序,而是使用-u(for独特的)结合-k 1,2指定由前 2 个字段组成的排序键(用于-k 1,19前 19 个字段),我们将删除前 2 个字段上的重复项。

如果文件未排序(至少在这两个字段上),则只需删除-m.但结果最终将被排序。排序会很昂贵,但在内存方面应该是可以的,因为使用临时文件对大文件进行排序(您需要(或)sort上的可用磁盘空间)。/tmp$TMPDIR

答案2

将相同的列组合起来形成索引是否有效?与您的上述例如。我们可以做——

 awk '{ind=""; for(i=1; i<3; i++) {ind=ind" "$i }  if (!arr[ind]) arr[ind]=$3  } END{for (i in arr) print i, arr[i]}'

  A 1 abc
  A 2 ttt
  B 2 ppp

您当然需要更改上面的循环以组合您需要的索引。

答案3

对于将来的情况,您可以这样做......并且您可以使用数组解决巨型文件的问题。每次字段值更改时,数组都会被删除。

BEGIN{
    xd=""; 
}
{
    id=$1;

    if (id != xd)
    {
        for (x in arr)
        {
            print x,arr[x];
        }

        delete arr; #Each time the field one changes its value
        xd=id;
    }
    ind="";
    for (i=1; i<3; i++)
    {
        ind=ind $i;
    }
    if (!arr[ind])
    {
        arr[ind]=$3;
    }

}

END {
        for (x in arr)
        {
            print x,arr[x];
        }
}

输出:

$ awk -f script.awk file.txt
A1 abc
A2 ttt
B2 ppp

答案4

试试这个:

awk '_a[$1" "$2]++==0'  < filename

相关内容