我有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,还是别的什么?
答案 0 :(得分: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进行反向依赖搜索非常棒)
答案 1 :(得分: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;