6

Perl を初めて使用するので、あなたの助けが必要です

xyz.csv次の内容の CSV ファイルがあります。

ここで level1 と er の値は文字列名です...数値ではありません...

level1,er
level2,er2
level3,er3
level4,er4

以下のスクリプトを使用してこの CSV ファイルを解析し、最初の実行でフィールドを配列に渡します。

open(my $d, '<', $file) or die "Could not open '$file' $!\n";
while (my $line = <$d>) {
  chomp $line; 
  my @data = split "," , $line; 
  @XYX = ( [ "$data[0]", "$data[1]" ], );
}

2 回目の実行では、コマンド プロンプトから入力を取得し、 variable に格納します$val。私のプログラムは、ファイルの最後に到達するまで、変数に格納されている値から CSV ファイルを解析する必要があります

例えば

ファイル内の前の値を無視して、 CSVlevel2ファイルの 2 行目から末尾までを解析するスクリプトが必要なので、level2これらの値 ( level2to level4) を@XYX = (["$data[1]","$data[1]"],);}

level2,er2
level3,er3
level4,er4

入力level3したので、CSV ファイルの 3 行目から末尾までを解析するスクリプトが必要です。level3ファイル内の前の値を無視し、これらの値 (level3およびlevel4) を@XYX = (["$data[0]","$data[1]"],);}

level3,er3
level4,er4

どうすればそれを達成できますか?あなたの貴重な提案をしてください。私はあなたの助けに感謝します

4

4 に答える 4

4

データにコンマが含まれていないことが確実である限り、 を使用しても問題ありませんsplit。それでも、最初のコンマまでのすべてとその後のすべてを取得できるように、分割を 2 つのフィールドに制限することが賢明です。

コードにはいくつかの問題があります。まず第一に、あなたがすべての Perl プログラムの先頭にuse strictとを置いていることを願っています。use warningsこの単純な方法で、他の方法では見逃す可能性のある多くの些細な問題を見つけることができるため、コードについて助けを求める前に特に重要です。

"\n"一般的には知られていませんが、文字列の最後に改行を置くdieと、エラーが発生した場所の出力で Perl がファイルと行番号の詳細を表示できなくなります。これはあなたが望むものかもしれませんが、通常は追加情報を提供する方が役に立ちます

変数名は非常に役に立たず、慣例により、Perl 変数は小文字の英数字とアンダースコアで構成されます。のような名前は@XYX$Wコードを理解するのにまったく役立ちません!

配列に分割するのではなく、2 つのフィールドを 2 つのスカラー変数に入れて、すべてのインデックス付けを回避する方がよいようです。そして、あなたが何を意図しているのかわかりません@XYX = (["$data[1]","$data[1]"],)。そもそも、本当に2回使うつもりなの$data[1]?第二に、スカラー変数を二重引用符で囲んではいけません。これは非常に具体的なことを行うためです。最後に、ループのたびpushに無名配列を使用するという意味でしたか? @XYXそうしないと、ファイルから行が読み取られるたびに配列の内容が上書きされ、以前のデータが失われます。

$level_numこのプログラムは、正規表現を使用して最初のフィールドから抽出します。文字列内の最初の一連の数字を検索し、それを最低限必要なレベルと比較して$min_level、ログの行が関連しているかどうかを判断します。

use strict;
use warnings;

my $file = 'xyz.csv';
my $min_level = 3;
my @list;

open my $fh, '<', $file or die "Could not open '$file' $!";

while (my $line = <$fh>) {
  chomp $line; 
  my ($level, $error) = split ',', $line, 2;
  my ($level_num) = $level =~ /(\d+)/;
  next unless $level_num >= $min_level;
  push @list, [ $level, $error ];
}
于 2012-08-31T12:57:09.593 に答える
1

..処理するレコードを決定するには、これらの行に沿って「フリップフロップ」演算子 ( ) を使用できます。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my $level = shift || 'level1';

while (<DATA>) {
  if (/^\Q$level,/ .. 0) {
    print;
  }
}

__DATA__
level1,er
level2,er2
level3,er3
level4,er4

フリップフロップ演算子は、最初のオペランドが true になるまで false を返します。その時点で、2 番目のオペランドが true になるまで false を返します。その時点で再び false を返します。

ファイルは、処理を開始したら停止したくないように順序付けられていると想定しています。つまり、フリップフロップの最初のオペランドは/^\Q$level,/(行頭の文字列$levelと一致する) で、2 番目のオペランドはゼロにすることができます (処理を停止したくないため)。

を使用して CSV レコードを解析しないことも強くお勧めしsplit /,/ます。これは現在のデータで機能する可能性がありますが、一般に、CSV ファイルのフィールドには、このアプローチを破る埋め込みカンマを含めることが許可されています。代わりに、Text::CSVまたはText::ParseWords (標準の Perl ディストリビューションに含まれています) を見てください。

更新:これについていくつかの反対票があったようです。人々が時間を割いて理由を説明してくれたら素晴らしいことです。

于 2012-09-01T12:30:05.043 に答える
1
#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV;

my @XYZ;
my $file = 'xyz.csv';
open my $fh, '<', $file or die "$file: $!\n";

my $level = shift; # get level from commandline
my $getall = not defined $level; # true if level not given on commandline

my $parser = Text::CSV->new({ binary => 1 }); # object for parsing lines of CSV

while (my $row = $parser->getline($fh)) # $row is an array reference containing cells from a line of CSV
{
  if ($getall # if level was not given on commandline, then put all rows into @XYZ
      or      # if level *was* given on commandline, then...
      $row->[0] eq $level .. 0 # ...wait until the first cell in a row equals $level, then put that row and all subsequent rows into @XYZ
     )
  {
    push @XYZ, $row;
  }
}

close $fh;
于 2012-09-02T13:38:23.093 に答える
1
#!/usr/bin/perl  
use strict;     
use warnings;
open(my $data, '<', $file) or die "Could not open '$file' $!\n"; 
my $level = shift ||"level1"; 
while (my $line = <$data>) {  
chomp $line; 
my @fields = split "," , $line; 
if($fields[0] eq $level .. 0){
print "\n$fields[0]\n";
print "$fields[1]\n";
}}

This worked....thanks ALL for your help...

于 2012-09-03T09:03:58.510 に答える