1

UnixでTSVファイルの4列目を指定された長さに切り捨てたい。ファイルには数百万のレコードがあり、サイズは8GBです。

私はこれを試していますが、少し遅いようです。

awk -F"\t" '{s=substr($4,0,256); print $1"\t"$2"\t"$3"\t"s"\t"$5"\t"$6"\t"$7}' file > newFile

同じためのより速い代替手段はありますか?

ありがとう

4

3 に答える 3

2

コマンドはもう少しうまく書くことができ(レコードを再構築していると仮定して)、パフォーマンスがいくらか向上する可能性があります。

awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,256) }' file > newFile

マルチコアマシンにアクセスできる場合(おそらくアクセスできます)、GNUパラレルを使用できます。使用するコアの数(ここでは4を設定)と供給されるブロックサイズawk(これを2メガバイトに設定)を変更することをお勧めします...

< file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' > newFile


これは、1億行でブロックサイズが2Mの2.7Gファイルを使用してシステムで行ったテストです。

time awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' file >/dev/null

結果:

real    1m59.313s
user    1m57.120s
sys     0m2.190s

1つのコアで:

time < file parallel -j 1 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null

結果:

real    2m28.270s
user    4m3.070s
sys     0m41.560s

4つのコアを使用:

time < file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null

結果:

real    0m54.329s
user    2m41.550s
sys     0m31.460s

12コアの場合:

time < file parallel -j 12 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null

結果:

real    0m36.581s
user    2m24.370s
sys     0m32.230s
于 2013-01-08T23:54:50.557 に答える
2

ファイルのフィールド間にスペース文字が1つだけあり、行の先頭に空白がないと仮定します。それが間違っている場合は、これを強化できます。それ以外の場合、これは機能するはずです。

sed 's/^\([^ ]* [^ ]* [^ ]* [^ ]\{1,256\}\)[^ ]* /\1 /'

256文字の長さのデータで実際にテストしたことはありません(テストしたところ\{1,2\}、速度がどのように比較されるかわかりませんawk。ところで、一部のバージョンでは、中括弧からバックスラッシュを省略する必要がある場合があります。とだけ使用し{1,256}ます。

于 2013-01-09T00:08:42.953 に答える
2

スコットまたはスティーブのソリューションがまだ遅すぎる場合は、Cを実行する時期かもしれません./a.out < file > newFile。最初にいくつかの長いフィールドを持つ小さなファイルでテストします。私は数学が正しいかどうか100%確信していません。

#include <stdio.h>
int
main(void)
{
    int field = 1;
    int character = 0;
    int c;
    while ((c = getchar()) != EOF)
    {
        switch (c)
        {
        case '\n':
            field = 1;
            character = 0;
            break;
        case '\t':
            character = 0;
            field++;
            break;
        default:
            character++;
            break;
        }
        if (field != 4 || character < 256)
            putchar(c);
    }
    if (ferror(stdout) || fflush(stdout) || fclose(stdout))
    {
        perror("write");
        return 1;
    }
    return 0;
}
于 2013-01-09T00:32:33.637 に答える