Perl循环卡住阅读文件?

时间:2009-06-23 13:57:03

标签: perl split readline while-loop

结束这个问题。会喝红牛。睡觉。代码并带着品牌打击单元测试用例的新问题。

更新:新文件为here

配置文件也是here

我再次重构了代码:

sub getColumns {
    open my $input, '<', $ETLSplitter::configFile
        or die "Error opening '$ETLSpliter::configFile': $!";

    my $cols;
    while( my $conline = <$input> ) {
        chomp $conline;
        my @values = split (/=>/, $conline);
        if ($ETLSplitter::name =~ $values[0] ) {
            $cols = $values[1];
            last;
        }
    }

    if($cols) {
        @ETLSplitter::columns = split (':', $cols);
    }
    else {
        die("$ETLSplitter::name is not specified in the config file");
    }
}

此代码始终在die("$ETLSplitter::name is not specified in the config file");处死亡。

另一个线索是,如果我将split (':', $cols);更改为split (/:/, $cols);,我会收到此错误。

 perl -wle "
 use modules::ETLSplitter;
 \$test = ETLSplitter->new('cpr_operator_metric_actual_d2', 'frame/');
 \$test->prepareCSV();"
 syntax error at modules/ETLSplitter.pm line 154, near "}continue"
 Compilation failed in require at -e line 2.
 BEGIN failed--compilation aborted at -e line 2.

4 个答案:

答案 0 :(得分:6)

此问题的最终发布次数:根据您的最新更新,我相信以下代码说明了使用/:/作为split的第一个参数时没有问题。它还指出,当使用函数的参数而不是依赖于全局变量时,读取代码会更容易:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

for my $varname ( qw( adntopr.cpr.smtref.actv cpr_operator_detail )) {
    print $varname, "\n";
    print Dumper get_columns(\*DATA, $varname);
}

sub get_columns {
    my ($input_fh, $varname) = @_;

    while ( my $line = <$input_fh> ) {
        chomp $line;
        my @values = split /=>/, $line;
        next unless $varname eq $values[0];
        return [ split /:/, $values[1] ];
    }
    return;
}

__DATA__
adntopr.cpr.smtref.actv=>3:8:18:29:34:38:46:51:53:149
adntopr.smtsale2=>3:8:16:22:27:37:39:47:52:57:62:82:102:120:138:234:239:244:249:250:259:262:277:282:287:289:304:319:327:331:335:339:340:341:342:353:364:375:386:397:408
cpr_operator_detail=>3:11:18:28:124:220:228:324
cpr_operator_org_unit_map=>7:12
cpr_operator_metric_actual=>8:15:25:33:38:40:51

C:\Temp> tjm
adntopr.cpr.smtref.actv
$VAR1 = [
          '3',
          '8',
          '18',
          '29',
          '34',
          '38',
          '46',
          '51',
          '53',
          '149'
        ];
cpr_operator_detail
$VAR1 = [
          '3',
          '11',
          '18',
          '28',
          '124',
          '220',
          '228',
          '324'
        ];

该代码中有很多错误。以下是我对你要做的事情的解释:

更新:鉴于您最近对模式中正则表达式特殊字符的评论,如果您要在模式中使用它们进行拆分,请务必引用它们。 $ETLSpliter::name也可能包含其他特殊字符。我修改了代码来处理这种可能性。

sub getColumns {
    open my $input, '<', $ETLSpliter::configFile
          or die "Error opening '$ETLSpliter::configFile': $!");
      my @columns;
      while( my $conline = <$input> ) {
          my @values = split /=>/, $conline;
          print "not at: ".$conline;
          push @columns, $values[1] if $values[0] =~ /\Q$ETLSpliter::name/;
      }
      return @columns;
  }

另一个更新:

因此,根据您在下面的评论,模式确实是/=>/。然后:

my $conline = q{cpr_operator_detail=>3:11:18:28:124:220:228:324};
my @values = split /=>/, $conline;

use Data::Dumper;
print Dumper \@values;
__END__

C:\Temp> tml
$VAR1 = [
          'cpr_operator_detail',
          '3:11:18:28:124:220:228:324'
        ];

没有错误 ... 没有警告 因此,还有其他一些事情你坚持不向我们展示。< / p>

其他备注:

  1. 使用词法文件句柄,让perl告诉你它可能遇到的错误而不是假设。

  2. 在最小适用范围内声明变量。

  3. 当您可以在$_声明中执行此操作时,无需在循环体中将$conline指定给while

  4. 在原始代码中,您没有在@columns中放置任何内容或对$colData执行任何有用的操作。

  5. 淡化这些言论。计算机按照GIGO的原则工作。

  6. 查看the link you posted处的代码,看起来您不知道可以这样做:

    use File::Spec::Functions qw( catfile );
    ...
    catfile($ETLSpliter::filepath_results, $ETLSpliter::actual_name);
    
  7. 此外,看起来你正在使用一个哈希就能完成这项工作的包:

    $ETLSpliter{filepath}
    

    最后,您确实意识到Spliter不正确。 ITYM:Splitter

答案 1 :(得分:3)

你确定它被卡住了吗?您永远不会在@columns中存储任何数据,因此您的代码将始终返回一个空列表。

其他说明:

  • 您的die来电应包含$!(操作系统错误)。除了不存在的文件之外,还有其他原因导致open失败,而$!会告诉您真正的问题是什么。
  • 你应该做chomp $conline来摆脱换行符。
  • 您可以执行while (my $conline = <CFILE>),而不是复制$_
  • 中的值
  • 双参数open(特别是隐式<模式)是不好的形式。首选使用三参数形式(理想情况下使用词法文件句柄):open(my $fh, '<', $filename) or die...

答案 2 :(得分:1)

$ETLSpliter::name中的内容 - 任何/字符都应该被转义。

该片段中的许多其他问题已经解决,因此我不会去那里。

答案 3 :(得分:0)

最终将其制作出来!!!!!哇睡觉真是太棒了。

反正。问题在于我的消息中的$ ETLSplitter :: configFile。

die ('Error opening '.$ETLSpliter::configFile.': '.$!);

哪个有winblows路径分隔符'/'。因为我用双引号输出,perl将路径中的'/'作为模式进行交错。从这里

die "Error opening some/path/to/ ...

...  /=>/, 

这与子程序中的整个程序流程相混淆。通过这样做解决了这个问题。

die ('Error opening '.$ETLSpliter::configFile.': '.$!);