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
同じためのより速い代替手段はありますか?
ありがとう
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
同じためのより速い代替手段はありますか?
ありがとう
コマンドはもう少しうまく書くことができ(レコードを再構築していると仮定して)、パフォーマンスがいくらか向上する可能性があります。
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
ファイルのフィールド間にスペース文字が1つだけあり、行の先頭に空白がないと仮定します。それが間違っている場合は、これを強化できます。それ以外の場合、これは機能するはずです。
sed 's/^\([^ ]* [^ ]* [^ ]* [^ ]\{1,256\}\)[^ ]* /\1 /'
256文字の長さのデータで実際にテストしたことはありません(テストしたところ\{1,2\}
、速度がどのように比較されるかわかりませんawk
。ところで、一部のバージョンでは、中括弧からバックスラッシュを省略する必要がある場合があります。とだけ使用し{1,256}
ます。
スコットまたはスティーブのソリューションがまだ遅すぎる場合は、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;
}