使用单个标量参数在Perl脚本中调用多个管道进行system()
调用。电话看起来或多或少是这样的:
system("zcat /foo.gz | grep '^.{6}X|Y|Z' | awk '{print $2,$3,$4,$6}' | bzip2 > /foo.processed.bz2");
有问题的文件(foo.gz
)非常大,压缩大小约2GB。我想这就是为什么它最初是通过系统调用完成的。
问题:
现在的问题是,无论其中一个系统命令是否失败,此系统调用似乎总是返回0。我认为这是因为它是通过sh -c '...'
调用的。这是对的吗?
如果只传递一个标量参数,有没有办法检查system()
调用是否成功?
有没有更好的方法来处理像这样的大文件,以同样或更高效的方式(主要是速度方面)?
感谢任何提示,因为我对Perl并不熟悉。
答案 0 :(得分:3)
两件事:
bzip2
命令的状态代码。对于像这样的事情,你最好使用Perl模块。在这种情况下,我敢打赌Perl模块将比shell管道更快,你可以更好地控制整个操作。
有一个名为IO::Compress的集合,可以处理Zip和BZip2。
我使用Archive::Zip这是一个很棒的模块,但你想使用Bzip2压缩算法,Archive::Zip
无法处理。
答案 1 :(得分:2)
system()
返回/bin/sh
shell返回的内容。当多个命令被流水线化时,shell会为每个命令分配一个新进程,并返回链中最后一个命令的状态代码,在本例中为bzip2
。
答案 2 :(得分:1)
根据您的评论和答案,我现在就这样做:
$infile =~ s/(.*\.gz)\s*$/gzip -dc < $1|/;
open(OUTFH, "| /bin/bzip > $outfile") or die "Can't open $outfile: $!";
open(INFH, $infile) or die "Can't open $infile: $!";
while (my $line = <INFH>) {
if ($line =~ /^.{6}X|Y|Z) {
# TODO: the awk part...
print OUTFH $line;
}
}
close(INFH);
close(OUTFH);
请随时评论并投票/投票。
答案 3 :(得分:-1)
你最好从perl本身进行文本处理 - 这就是perl的用途:)
system()只返回0或1.要捕获实际输出,请尝试通过反引号调用它:`command`而不是system('command')