perl系统调用不是随机执行的

时间:2014-07-28 17:14:56

标签: perl exec

在perl脚本的循环结构中,我编写了以下行来使用系统工具解析文本文件,在进程中生成临时文本文件,然后将临时输出读入数组以便在perl脚本中进行处理:

system("awk '(NR+2)%4==0' $infile[$i+$j] | tre-agrep -ns -E $dist[$a][$b] -k $query[$a][$b] | awk 'BEGIN{FS=\":\";OFS=\":\"}{print \$1,\$2}' > $outfile");
open(my $FH, "<", $outfile) || die "Can't open $outfile: $!";
while(<$FH>) {
  ...
}
close($FH);

这些命令几乎逐字地重复两次(修改了一些参数,但是文件句柄的循环),循环结构本身被多次迭代。出乎意料地并且看似随意,程序有时无法完成系统调用,导致依赖于系统调用生成的输出的后续行依次失败,触发脚本中止并显示相当无用的错误消息“没有这样的文件或目录“(参考open语句)。直接从控制台而不是在perl脚本的上下文中执行相同的系统调用会显示该命令产生预期的输出。我将此行为称为任意行为,因为有时我的脚本将在open行失败之前以各种方式完成1到3次迭代,并且不同成功的基础尚不清楚。当脚本正常工作时,系统调用需要相当长的时间(大约2分钟),而当它失败时,程序会在不到一秒的时间内移动到以下open行。因此,我想弄清楚为什么有时会跳过系统调用。

脚本在bash shell会话中运行,脚本标题中包含以下内容:

#! /usr/bin/perl
use warnings;
use strict;

1 个答案:

答案 0 :(得分:2)

我从根本上同意@ThisSuitIsBlackNot。但是,不知道tre-agrep是什么,将该部分转换为直接Perl很困难。

那说,至少,为什么不跳过输出文件的生成并直接从Perl读取Unix输出?

open my $FH, '-|', "awk '(NR+2)%4==0' $infile[$i+$j] | " .
    "tre-agrep -ns -E $dist[$a][$b] -k $query[$a][$b]" or die "$!";
while (<$FH>) {
  chomp;
  my ($field1, $field2) = split /:/, $_, 2;
}
close $FH;

在最糟糕的情况下,系统调用的标准输出将是空白的,但这不会影响Perl读取任何内容的能力(因此无效)。

当然,首先执行-e(存在)调用以确保infile[$i + $j]不是幽灵并不会有什么坏处。