0

次のような Perl と CSV ファイルがあります。

"Name","Lastname"
"Homer","Simpsons"
"Ned","Flanders"

この CSV ファイルでは、最初の行にヘッダーがあり、他の行にはデータがあります。

この CSV ファイルを次のような Perl データに変換したい:

[
    {
        Lastname => "Simpsons",
        Name     => "Homer",
    },
    {
        Lastname => "Flanders",
        Name     => "Ned",
    },
]

Text::CSVを使用して必要なことを行う関数を作成しました。サンプル スクリプトは次のとおりです。

#!/usr/bin/perl

use strict;
use warnings FATAL => 'all';
use 5.010;
use utf8;
use open qw(:std :utf8);

use Text::CSV;

sub read_csv {
    my ($filename) = @_;

    my @first_line;
    my $result;

    my $csv = Text::CSV->new ({ binary => 1, auto_diag => 1 });
    open my $fh, "<:encoding(utf8)", $filename or die "$filename: $!";
    while (my $row = $csv->getline ($fh)) {
        if (not @first_line) {
            @first_line = @{$row};
        } else {
            push @{$result}, { map { $first_line[$_] => $row->[$_] } 0..$#first_line };
        }
    }
    close $fh;

    return $result;
}

my $data = read_csv('sample.csv');

これは正常に機能しますが、この関数をいくつかのスクリプトで使用したいと考えています。Text::CSV にこの機能がないことに非常に驚いています。

私の質問。将来、自分や他の人がそのようなタスクを簡単に解決できるようにするにはどうすればよいですか?

CPAN の Perl モジュールを使用する必要がありますか? この関数を Text::CSV などに追加する必要がありますか?

4

2 に答える 2

3

は?なぜそんなに複雑なのですか?まず、ループの外でヘッダーをフェッチします。

my $headers = $csv->getline($fh) or die "no header";

これらを列名に割り当てます。

$csv->column_names(@$headers);

次に、 を呼び出すたびgetline_hrに hashref が提供されます。

while (my $hashref = $csv->getline_hr($fh)) {
  push @$result, $hashref;
}

も使用できますgetline_hr_all

$result = $csv->getline_hr_all($fh);

言い換えれば、複雑ではなく、ほとんどの部分はすでに によって提供されておりText::CSV、非常に数行で実行できます。

また、このようなモジュールは既に存在しているようです: Text::CSV::Slurp. (注: metacpan による逆依存検索はすばらしい)

于 2013-06-26T10:50:41.103 に答える
0

さまざまな人が CSV ファイルをさまざまなデータ構造に解析する必要があるため、これはおそらく標準機能ではありません。

この関数をラップする独自のモジュールを作成してみませんか?

package CSVRead;

use strict;
use warnings;
use 5.010;
use open qw(:std :utf8);

use Text::CSV;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(read_csv);

sub read_csv {
    my ($filename) = @_;

    my @first_line;
    my $result;

    my $csv = Text::CSV->new ({ binary => 1, auto_diag => 1 });
    open my $fh, "<:encoding(utf8)", $filename or die "$filename: $!";
    while (my $row = $csv->getline ($fh)) {
        if (not @first_line) {
            @first_line = @{$row};
        } else {
            push @{$result}, { map { $first_line[$_] => $row->[$_] } 0..$#first_line };
        }
    }
    close $fh;

    return $result;
}

次に、次のように使用します。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Data::Dumper;
use CSVRead;

my $data = read_csv('sample.csv');

say Dumper $data;
于 2013-06-26T10:54:18.633 に答える