我有一个看起来像这样的文件:
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