大きなファイルから最初の数列が同じ2行目を削除する

大きなファイルから最初の数列が同じ2行目を削除する

次のファイルがあります。

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

最初の2つのキーが同じ場合、最初の行を維持したいと思います。これを行います。

A 1 abc
A 2 ttt
B 2 ppp

私が一つ見つけた前の質問これで問題が解決しました。しかし、私のファイルサイズは1.2GBで、最初の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(例:ユニーク-k 1,2)最初の2つのフィールド(最初の19フィールド)で構成されたソートキーを指定することと組み合わせて、-k 1,19最初の2つのフィールドから重複する項目を削除します。

ファイルがソートされていない場合(少なくとも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

関連情報