在Unix中有没有更快的截断列的方法

在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,

我想在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
如果您可以访问多核机器,您可以使用。你可能想改变你使用的核心数量,我在这里设置了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.outnewFile的方式运行了。首先在带有一些长字段的小文件上进行测试;我不是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;
}

如果Scott或Steve的解决方案仍然太慢,那么可能是时候打破C.runas./a.outnewFile了。首先在带有一些长字段的小文件上进行测试;我不是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;
}

现在有多快?你要多快?如果没有数字,你就无法有意义地谈论性能。现在的速度有多快?你要多快?如果没有数字,你就无法有意义地谈论性能。非常感谢你在研究方面的努力。我并不是要比较所有方法在几秒钟内的性能。我问这个问题只是为了确保我的方法不是超低效的。非常感谢这些研究工作。我并不是要比较所有方法在几秒钟内的性能。我问这个问题只是为了确保我的方法不是超低效的。