2

〜20GBのcsvファイルがあります。サンプルファイル:

1,a@a.com,M
2,b@b.com,M
1,c@c.com,F
3,d@d.com,F

このファイルの主キーは最初の列です。uniq.csv と duplicates.csv の 2 つのファイルを作成する必要があります。

uniq.csv にはすべての重複しないレコードが含まれている必要があり、duplicates.csv には現在のタイムスタンプを持つすべての重複レコードが含まれます。

uniq.csv

1,a@a.com,M
2,b@b.com,M
3,d@d.com,F

重複.csv

2012-06-29 01:53:31 PM, 1,c@c.com,F

外部R-Wayマージソートアルゴリズムを利用できるように、Unix Sortを使用しています

To identify uniq records
tail -n+2 data.txt | sort -t, -k1 -un > uniq.csv

To identify duplicate records
awk 'x[$1]++' FS="," data.txt | awk '{print d,$1}' "d=$(date +'%F %r')," > duplicates.csv

この大きなファイルを 1 回スキャンするだけで、重複と一意の両方を見つける方法があるのではないかと考えていました。

4

3 に答える 3

2

あなたのawkスクリプトはもうすぐそこにあります。一意の行を見つけるには、in演算子を使用して、エントリが関連配列にあるかどうかをテストするだけです。これにより、データ ファイルを介して 1 回のパスでデータを収集でき、 を呼び出す必要がなくなりますsort

tail -n +2 data.txt | \
awk '
    BEGIN { OFS=FS="," }
    {
        if (!($1 in x)) {
            print $0 > "/dev/fd/3"
        }
        x[$1]++
    }
    END {
        for (t in x) {
            print d, t, x[t]
        }
    }' d="$(date +'%F %r')" 3> uniq.csv > duplicates.csv
于 2012-07-01T13:41:48.667 に答える
0

これは、1回のスキャンで処理を行うperlのコードです。

#!/usr/bin/perl
open(FI,"sort -t, -k1 < file.txt |");
open(FD,">duplicates.txt");
open(FU,">uniques.txt");
my @prev;
while(<FI>)
{
    my (@cur) = split(',');
    if($prev[0] && $prev[0]==$cur[0])
    {
        print FD localtime()." $_";
    }
    else
    {
        print FU $_;
    }
    @prev=@cur;
}
于 2012-06-19T22:06:14.537 に答える
0

この質問は、数年前の面接で受けました。

1 つの答えは、"-c" (カウント) オプションを指定して uniq を使用することです。カウントが「1」のエントリは一意であり、それ以外の場合は一意ではありません。

並べ替え foo | ユニーク -c | awk '{ if ($1 == 1) { write-to-unique } else {write-to-duplicate }'

専用のプログラムを作成したり、ソートによる遅延を回避したい場合は、Python を使用します。

入力ファイルを読み取り、各エントリをハッシュし、遭遇した一意のキーごとに整数値を ++ します。2 つの項目が等しくない場合でもハッシュ値が衝突する可能性があることに注意してください。そのため、各キーをそのカウントとともに個別に保持してください。入力の EOF で、ハッシュ構造をトラバースし、各エントリを 2 つのファイルのいずれかに吐き出します。

ソートされた出力は必要ないようで、分類された出力のみが必要なようです。したがって、ハッシュはより高速になるはずです。ハッシュの構築は O(1) ですが、並べ替えは O(忘れました; UNIX の並べ替えは Nlog(N) ですか?)

于 2012-06-19T21:41:02.717 に答える