我有一个包含两个字段的大型(3GB)gzip压缩文件:NAME和STRING。我想将此文件拆分为较小的文件 - 如果字段1是john_smith,我希望将字符串放在john_smith.gz中。注意:字符串字段可以并且确实包含特殊字符。
我可以使用BASH轻松地在域中进行for循环,但我更喜欢使用AWK一次读取文件的效率。
我尝试在awk中使用系统函数,并在字符串
周围使用转义单引号zcat large_file.gz | awk'{system(“echo -e'”'“'”$ 1“\ t”$ 2“'”'“'| gzip>>”$ 1“.gz”);}'
并且它在大多数行上都能正常工作,但是其中一些行被打印到STDERR并且给出了shell无法执行命令的错误(shell认为字符串的一部分是命令)。看起来特殊字符可能会破坏它。
有关如何解决此问题的任何想法,或任何有用的替代实现?
谢谢!
-Sean
答案 0 :(得分:2)
你面临着与磁盘空间相关的重大折衷。 我假设你试图通过将记录附加到$ {name} .gz文件的末尾来节省空间。 @sehe评论和代码绝对值得考虑。
无论如何,你的时间比3 GB的磁盘空间更有价值。为什么不试试
zcat large_file.gz \
| awk '-F\t' {
name=$1; string=$2; outFile=name".txt"
print name "\t" string >> outFile
# close( outFile)
}'
echo *.txt | xargs gzip -9
您可能需要取消注释#close(outFile)。 包含xargs是因为我假设您将创建更多的1000个文件名。即使你不这样做也不会伤害使用这种技术。
请注意,此代码假设制表符分隔数据,根据需要更改-F的arg值以及打印参数中的“\ t”以提供所需的字段分隔符。
没时间测试这个。如果您喜欢这个想法并且卡住了,请发布您收到的小样本数据,预期输出和错误消息。
我希望这会有所帮助。
答案 1 :(得分:0)
创建此程序,例如largesplitter.c
并使用命令
zcat large_file.gz | largesplitter
朴实无缺的计划是:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main (void)
{
char buf [32000]; // todo: resize this if the second field is larger than
char cmd [120];
long linenum = 0;
while (fgets (buf, sizeof buf, stdin))
{
++linenum;
char *cp = strchr (buf, '\t'); // identify first field delimited by tab
if (!cp)
{
fprintf (stderr, "line %d missing delimiter\n", linenum);
continue;
}
*cp = '\000'; // split line
FILE *out = fopen (buf, "w");
if (!out)
{
fprintf (stderr, "error creating '%s': %s\n", buf, strerror(errno));
continue;
}
fprintf (out, "%s", cp+1);
fclose (out);
snprintf (cmd, sizeof cmd, "gzip %s", buf);
system (cmd);
}
return 0;
}
这在我的系统上编译没有错误,但我还没有测试它的功能。
答案 2 :(得分:0)
也许尝试一下以下几点:
zcat large_file.gz | echo $("awk '{system("echo -e '"'"'"$1"\t"$2"'"'"' | gzip >> "$1".gz");}'")
我自己没有尝试过,因为我没有任何大文件可供使用。
答案 3 :(得分:0)
这个小的perl脚本很好地完成了这项工作
gzip
管道输出 $fh
存在一些问题,因为显然直接使用哈希条目不起作用
#!/usr/bin/perl
use strict;
use warnings;
my $suffix = ".txt.gz";
my %pipes;
while (my ($id, $line) = split /\t/,(<>),2)
{
exists $pipes{$id}
or open ($pipes{$id}, "|gzip -9 > '$id$suffix'")
or die "can't open/create $id$suffix, or cannot spawn gzip";
my $fh = $pipes{$id};
print $fh $line;
}
print STDERR "Created: " . join(', ', map { "$_$suffix" } keys %pipes) . "\n"
哦,像
一样使用它zcat input.gz | ./myscript.pl