Perlループがファイルの読み取りでスタックしましたか?
-
06-07-2019 - |
質問
この質問を終了します。レッドブルを飲みます。睡眠。ユニットテストケースを使用して、新しい質問をコーディングしてブランドに戻ってください。
更新:新しいファイルはこちら
また、設定ファイルはこちら
コードを再度リファクタリングしました:
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.
解決
この質問の最終投稿:最新の更新に基づいて、次のコードは/:/
の最初の引数として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'
];
エラーなし ... 警告なし したがって、私たちを見せないことを主張している何か他のものがあります。
その他のコメント:
-
レキシカルファイルハンドルを使用し、perlが推測するのではなく、発生する可能性のあるエラーを教えてください。
-
適用可能な最小のスコープで変数を宣言します。
-
$_
ステートメントで実行できる場合、ループの本体で$conline
にwhile
を割り当てる必要はありません。 -
元のコードでは、
@columns
に何かを入れたり、$colData
で何か便利なことをしたりしていませんでした。 -
レトリックを調整します。コンピューターはGIGOの原則に基づいて動作します。
-
投稿したコードのコードを見ると、そうではないようですあなたができることに注意してください:
use File::Spec::Functions qw( catfile ); ... catfile($ETLSpliter::filepath_results, $ETLSpliter::actual_name);
さらに、ハッシュを使用してパッケージを使用しているように見えます:
$ETLSpliter{filepath}
最後に、Spliter
が間違っていることに気付きます。 ITYM:Splitter
。
他のヒント
それがスタックしていることは確かですか? @columns
にはデータを保存しないため、コードは常に空のリストを返します。
その他の注意:
-
die
呼び出しには$!
(OSエラー)を含める必要があります。存在しないファイル以外にopen
が失敗する可能性のある他の理由があり、chomp $conline
は実際の問題が何であるかを教えてくれます。 - おそらく
while (my $conline = <CFILE>)
を実行して、改行を削除する必要があります。 -
$_
から値をコピーする代わりに<
を実行できます。 - 2つの引数
open(my $fh, '<', $filename) or die...
(特に暗黙的な<=>モードの場合)は、形式が貧弱です。 3つの引数形式(理想的にはレキシカルファイルハンドル)を使用することをお勧めします:<=>
$ETLSpliter::name
の内容-そこにある/
文字はすべてエスケープする必要があります。
スニペットの他の多くの問題はすでに対処されているため、ここには行きません。
最終的にそれを計算しました!!!!!すごい睡眠は素晴らしいパワーです。
とにかく。問題は、ダイメッセージの$ ETLSplitter :: configFileにありました。
die ('Error opening '.$ETLSpliter::configFile.': '.$!);
Winblowsパス区切り文字「/」があります。そのため、二重引用符で出力しているため、perlはパスに「/」をパターンとして挿入しました。ここから
die "Error opening some/path/to/ ...
to
... /=>/,
サブルーチン内のプログラムフロー全体を台無しにしました。これはこれを行うことで解決しました。
<*>