3

AIX を使用しないマシンでPERLは、同じ ID を持ち、4 時間の間に登録された場合に重複していると見なされるレコードをフィルター処理する必要があります。

私はこのフィルターを使用して実装しAWK、かなりうまく機能しますが、もっと速い解決策が必要です:

# Duplicados の一般的なリスト
awk 'BEGIN {
FS=","
}
/わかった/ {
    古い[$8] = f[$8];
    f[$8] = mktime($4, $3, $2, $5, $6, $7);
    x[$8]++;
}
/OK/ && x[$8]>1 && f[$8]-old[$8]

助言がありますか?環境を改善する方法はありますか (ファイルのプリロードなど)。

入力ファイルは既にソートされています。

jj33によって提案された修正により、日付の処理を改善した新しいバージョンを作成しましたが、より多くの操作を組み込むために目立たないように維持しています。

awk 'BEGIN { FS=","; SECSPERMINUTE=60; SECSPERHOUR=3600; SECSPERDAY=86400; split("0 31 59 90 120 151 181 212 243 273 304 334", DAYSTOMONTH, " "); split("0 366 731 1096 1461 1827 2192 2557 2922 3288 3653 4018 4383 4749 5114 5479 5844 6210 6575 6940 7305", DAYSTOYEAR, " "); } /わかった/ { 古い[$8] = f[$8]; f[$8] = mktime($4, $3, $2, $5, $6, $7); x[$8]++; } /OK/ && x[$8]>1 && f[$8]-old[$8] 2 ) && ( ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 = = 0) ) ) { d2m = d2m + 1; } d2y = DAYSTOYEAR[y - 1999]; return ss + (mm*SECSPERMINUTE) + (hh*SECSPEROUR) + (d*SECSPERDAY) + (d2m*SECSPERDAY) + (d2y*SECSPERDAY); } '
4

6 に答える 6

3

これは実際のデータベースの仕事のように聞こえます。SQLiteのようなものでさえ、おそらくここでかなりうまく役立つでしょう。私が見る大きな問題は、「4時間以内」の定義です。これはスライディングウィンドウの問題です。つまり、すべてのデータを4時間のセグメントに単純に量子化することはできません...他のすべての要素のすべての「近くの」要素を個別に計算する必要があります。うーん。

于 2008-10-05T06:29:33.500 に答える
1

@ AnotherHowie、前処理全体をsortとuniqで実行できると思いました。問題は、OPのデータがコンマで区切られているように見え、(Solaris 8の)uniqではレコード区切り文字を指定できないため、標準のUNIXツールを使用して前処理を行うための非常にクリーンな方法がなかったことです。これ以上速くなるとは思わないので、正確なオプションを調べるつもりはありませんが、次のようなことができます。

cut -d, -f8 <infile.txt | sort | uniq -d | xargs -i grep {} infile.txt >outfile.txt

重複するキーを含むすべての行に対してgrepを実行するため、これはあまり良くありません。おそらく、uniq出力を単一の正規表現にマッサージしてgrepにフィードすることもできますが、OPが、ファイル内の合計行に対する疑わしい重複キーを含む行の予想される比率を投稿する場合にのみ、利点がわかります。

于 2008-08-11T13:07:51.987 に答える
1

うるう年を考慮する必要があると思います。私は数学をしませんでしたが、うるう年の間に、2月のハードコードが28日であるため、2/29の正午と3/1の正午を比較すると、以前と同じタイムスタンプが重複することになります。 。あなたはそれをそのように実装しなかったように見えますが。彼らはあなたがそれを実装した方法で、あなたはまだ問題を抱えていると思いますが、それは$leapyearの12/31と$leapyear+1の1/1の日付の間です。

コードがそれらを処理するタイムゾーンを処理する必要がある場合は、時間の変更中に衝突が発生する可能性もあると思います。

ファイルは実際には有用な方法でソートされていないようです。フィールド$1はある種のステータス(チェックしている「OK」)だと思います。つまり、レコードステータス、DAY、MONTH、YEAR、HOURS、MINUTES、SECONDSの順に並べ替えられます。年、月、日であれば、そこにいくつかの最適化があると思います。まだそうかもしれませんが、私の脳は今、別の方向に進んでいます。

行の総数に比例して重複するキーの数が少ない場合、最善の策は、awkスクリプトが処理するファイルを重複するキーだけに減らすことだと思います(Davidが言ったように)。ファイルを前処理して、存在する行が/OK/行だけになるようにすることもできます。これは、最初のawkスクリプトが重複するIDの行のみを出力し、2番目のawkスクリプトが基本的に上記のものであるが、/ OK /を検索しないように最適化されており、存在するキーがキーが重複しています。

すべてまたはほとんどの行にキーが繰り返されることが事前にわかっている場合は、いじる価値はないでしょう。弾丸を噛んでCで記述します。awkスクリプトよりもはるかに高速なコード行がたくさんあります。

于 2008-08-10T03:12:10.240 に答える
1

入力ファイルはどのようにソートされますか? cat file|sort のように、または単一の特定のフィールドまたは複数のフィールドを介してソートしますか? 複数のフィールドの場合、どのフィールドとどの順序ですか? 時間フィールドは 12 時間制ではなく 24 時間制のようですよね?すべての日付/時刻フィールドにゼロが埋め込まれていますか (午前 9 時は "9" または "09" になりますか?)

パフォーマンスを考慮しないと、すべての月が 30 日の長さであると想定されているため、コードに月の境界に関する問題があるように見えます。2008-05-31/12:00:00 と 2008-06-01:12:00:00 の 2 つの日付を取ります。これらは 24 時間離れていますが、コードは両方に対して同じタイム コードを生成します (63339969600)

于 2008-08-09T18:41:47.977 に答える
1

多くの unixen では、特定の列またはフィールドで並べ替えることができます。そのため、ファイルを ID で並べ替え、次に日付で並べ替えると、各 ID を最後に見たときの連想配列を保持する必要がなくなります。すべてのコンテキストがファイルの順序で存在します。

GNU ソートを備えた私の Mac では、次のようになります。

sort -k 8 < input.txt > output.txt

ID フィールドでソートします。代わりに (例) 8,3 と言って、2 番目のフィールドでも並べ替えることができますが、2 つのフィールドのみです。したがって、UNIX スタイルの time_t タイムスタンプは、ファイルで悪い考えではないかもしれません。並べ替えが簡単で、日付の計算をすべて保存できます。また、(少なくとも GNU awk では)コンポーネントから time_t を作成するmktime 関数があります。

于 2008-08-10T14:51:02.187 に答える
1

データ ファイルにすべてのレコードが含まれている場合 (つまり、ファイル内に重複 ID を持たないレコードが含まれている場合)、前処理して、重複 (ID) を持つレコードのみを含むファイルを生成できます。

これがファイルのサイズを減らす場合は、AWK プログラムで処理する必要があります。

于 2008-08-09T15:25:29.980 に答える