使用Perl中的单个标量参数调用system()的退出代码

时间:2011-11-22 12:46:21

标签: perl

使用单个标量参数在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并不熟悉。

4 个答案:

答案 0 :(得分:3)

两件事:

  1. 执行系统调用时,返回的值是管道中的最后一个值。因此,您将获得bzip2命令的状态代码。
  2. 程序执行此操作的原因是因为编写程序的人可能不知道更好。我见过Perl程序使用系统调用来查找文件的基本名称,进行查找,甚至进行复制/重命名/移动。这些都可以在Perl程序中更快更容易地完成。而且,您没有整个Windows / Unix兼容性问题。
  3. 对于像这样的事情,你最好使用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')