2016-08-29 4 views
-2

私のCSVファイルの最初の行には、以下のフィールドの名前が含まれています。 ファイルを配列の配列に読み込み、0行目のシフトを試みます。perl:配列の配列から配列をシフトすると、特別なレベルの間接参照が追加されるのはなぜですか?

しかし、配列は別の配列レベルでラップされているようです。

どのようにして間接的にレベルを上げることができますか?

ここでは、コードです:

open CSV, "ExDivExport.csv" or die;; 
@fields=(); 
while (<CSV>) 
{ chomp; 
    ($temp) = /^"(.+)"$/; # remove first and last " 
    @line=split /","/, $temp ; 
    print"\[email protected]"; # all the lines print correctly here 
    push @fields, [@line]; 
} 
@names = shift @fields; # Here I shift off the 0th row 

print "\nat12 [email protected]";   # prints: ARRAY(0x26e52c) 
print "\nat13 names[0]=$names[0]"; # prints ARRAY(0x26e52c) 
print "\nat14 names[0][0]=$names[0][0]"; # correctly prints first name 'Symbol' 
+1

余分なレベルのインダイレクションを取り除くと、csvファイルのすべての行の値がすべて1つの配列になります。あなたが本当に欲しいのはそれですか? – xxfelixxx

+3

いずれにしても、自分でcsvを解析するべきではありません。ライブラリを使用する必要があります。そうしないと、エッジケースで噛まれる可能性があります。 'Text :: CSV'は良い選択でしょう:http://search.cpan.org/~makamaka/Text-CSV-1.33/lib/Text/CSV.pm – xxfelixxx

+2

余分なレベルはあなたが' @line] 'を' @ fields'配列に追加します。 '[...]'は内容を配列リファレンスにラップします。 – xxfelixxx

答えて

1

あなたのコード@fields変数に配列にreferenceを格納し、それはあなたがこの種のデータを抽出しようとする方法を変更する必要があります:

$names = shift @fields;    # get a reference, so use $ sigil (scalar) 
print "\nat12 [email protected]$names";   # dereference array ref 
print "\nat13 names[0]=$names->[0]"; # get the first element (access with -> notation) 

は、私はあなたが学習目的のためにそれを試みていると思います。他の方法として、CSVの解析を真剣に検討している場合は、Text::CSVのように、CPANのよくテストされ、文書化されたモジュールを使用する方が良いでしょう。

また、デバッグの目的で、変数の構造を分析する場合は、Data::Dumperを理解するのに役立ちます。例:

print Dumper(\@names), "\n"; 

コードで古い形式でファイルを開きます。 3つのparamsを使用して近代的なアプローチがあります:

open CSV, "ExDivExport.csv" or die;; 

open my $CSV, '<', 'ExDivExport.csv' or die "cannot open file: $!"; 
#... then use the lexical variable $CSV instead of the CSV bareword 

でなければなりませんし、私がしなければならなかったすべては置き換えたので、close $CSV;

+0

私が$ names = shift @fieldsと言うとき、 、私はちょうど同じ配列への参照を取得しているので、すべてのメンバーは最後の配列を指すようになります。私は深いコピーを渡す必要があります。 – user1067305

+0

@ user1067305:あなたの番組よりもあなたが示している以上に多くのことがあり、別の質問をする必要があります。 – Borodin

+0

@ user1067305なぜディープコピーが必要ですか? "shift"は古い配列を外側の配列から削除し、それは失われます。 – Mike

0

することを忘れないでください:

@names = shift @fields;

@names = @ {シフト@fields}と

問題を解決しました。

+0

あなたが知っているように、「間接レベル」は「シフト」によって*追加されませんでした。それは*すべての行*にありますが、あなたは名前のリストを抽出するためにそれを削除したいと思っていました。 – dolmen

+0

それは畏敬の念を抱く解決策です。それは不必要に配列のコピーを作成します。前述したように、あなたは 'my $ names = shift @fields;'を使うべきです。 – ikegami

関連する問題