在Unix中有没有更快的截断列的方法
我想在Unix中将TSV文件的第4列截断为给定长度。该文件有数百万条记录,大小为8GB 我正在尝试,但似乎有点慢在Unix中有没有更快的截断列的方法,unix,Unix,我想在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,
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
如果您可以访问多核机器,您可以使用。你可能想改变你使用的核心数量,我在这里设置了4个,并且输入到awk的块大小,我已经设置为2兆字节
< file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' > newFile
结果:
real 1m59.313s
user 1m57.120s
sys 0m2.190s
real 2m28.270s
user 4m3.070s
sys 0m41.560s
real 0m54.329s
user 2m41.550s
sys 0m31.460s
real 0m36.581s
user 2m24.370s
sys 0m32.230s
有一个核心:
time < file parallel -j 1 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
有四个核心:
time < file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
12芯:
time < file parallel -j 12 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
假设您正在重新构建记录,那么您的命令可以写得更漂亮一些,这可能会提高一些性能:
awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,256) }' file > newFile
如果您可以访问多核机器,您可以使用。你可能想改变你使用的核心数量,我在这里设置了4个,并且输入到awk的块大小,我已经设置为2兆字节
< file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' > newFile
结果:
real 1m59.313s
user 1m57.120s
sys 0m2.190s
real 2m28.270s
user 4m3.070s
sys 0m41.560s
real 0m54.329s
user 2m41.550s
sys 0m31.460s
real 0m36.581s
user 2m24.370s
sys 0m32.230s
有一个核心:
time < file parallel -j 1 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
有四个核心:
time < file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
12芯:
time < file parallel -j 12 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null
我假设您的文件在字段之间只有一个空格字符,并且行的开头没有空格。如果这是错误的,可以对此进行增强 否则,这应该是可行的:
sed 's/^\([^ ]* [^ ]* [^ ]* [^ ]\{1,256\}\)[^ ]* /\1 /'
实际上,我没有用256个字符长的数据对它进行测试,我用\{1,2\}对它进行了测试,我不知道它的速度与awk的速度相比如何。顺便说一句,在某些版本上,您可能需要去掉大括号中的反斜杠,只使用{1256}.我将假定您的文件在字段之间只有一个空格字符,并且行的开头没有空格。如果这是错误的,可以对此进行增强 否则,这应该是可行的:
sed 's/^\([^ ]* [^ ]* [^ ]* [^ ]\{1,256\}\)[^ ]* /\1 /'
实际上,我没有用256个字符长的数据对它进行测试,我用\{1,2\}对它进行了测试,我不知道它的速度与awk的速度相比如何。顺便说一句,在某些版本上,你可能需要去掉大括号中的反斜杠,只使用{1256}。如果Scott或Steve的解决方案仍然太慢,也许是时候打破C.以/a.out
#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;
}
如果Scott或Steve的解决方案仍然太慢,那么可能是时候打破C.runas./a.out
#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;
}
现在有多快?你要多快?如果没有数字,你就无法有意义地谈论性能。现在的速度有多快?你要多快?如果没有数字,你就无法有意义地谈论性能。非常感谢你在研究方面的努力。我并不是要比较所有方法在几秒钟内的性能。我问这个问题只是为了确保我的方法不是超低效的。非常感谢这些研究工作。我并不是要比较所有方法在几秒钟内的性能。我问这个问题只是为了确保我的方法不是超低效的。