【问题标题】:How to load a CSV file into a perl hash and access each element如何将 CSV 文件加载到 perl 哈希中并访问每个元素
【发布时间】:2019-02-19 16:23:04
【问题描述】:

我有一个 CSV 文件,其中包含以下用逗号分隔的信息...

Owner,Running,Passing,Failing,Model
D42,21,54,543,Yes
T43,54,76,75,No
Y65,76,43,765,Yes

我想打开这个 CSV 文件并将其包含在我的程序中的 perl 哈希中。我也对在 has 中打印特定元素所需的代码感兴趣。例如,我将如何打印“所有者”Y65 的“通过”计数。

我目前拥有的代码:

$file = "path/to/file";

open $f, '<', $files, or die "cant open $file"

while (my $line = <$f>) {

#inside here I am trying to take the containments of this file and place it into a hash. I have tried numerous ways of trying this but none have seemed to work. I am leaving this blank because I do not want to bog down the visibility of my code for those who are kind enough to help and take a look. Thanks.

}

除了将 csv 文件放在散列中外,我还需要了解打印和浏览特定元素的语法。非常感谢您。

【问题讨论】:

  • 是的,这很容易,但希望您展示您所尝试的内容。请发布您正在努力的代码。请参阅How to ask了解更多信息
  • @hakonhagland 我发布了一些我拥有的代码。我最初没有发布它,因为我不想在我的错误代码中阻碍任何人的视野。提前致谢。
  • 好的,下一步是用逗号分割每一行。您可以尝试使用split 函数或更高级的Text::CSV 模块。然后将第一项(所有者)用作哈希键,将其余项用作值(数组),并将其保存到 %owners 哈希中...
  • @hakonhagland 谢谢你的帮助。我已经完全按照您告诉我的方法进行了尝试,但未能达到稳定的输出。您是否可以针对该问题编写一些示例代码以将我推向正确的方向?任何帮助是极大的赞赏。非常感谢
  • 考虑使用CPAN模块Text::CSV::Hashify

标签: file perl csv


【解决方案1】:

这是一个如何将数据放入哈希%owners 的示例,然后(在读取文件后)为特定所有者提取“通过计数”。我正在使用Text::CSV 模块来解析文件的行。

use feature qw(say);
use open qw(:std :utf8);  # Assume UTF-8 files and terminal output
use strict;
use warnings qw(FATAL utf8);
use Text::CSV;

my $csv = Text::CSV->new ( )
  or die "Cannot use CSV: " . Text::CSV->error_diag ();
my $fn = 'test.csv';
open my $fh, "<", $fn
  or die "Could not open file '$fn': $!";
my %owners;
my $header = $csv->getline( $fh );  # TODO: add error checking 
while ( my $row = $csv->getline( $fh ) ) {
    next if @$row == 0; # TODO: more error checking
    my ($owner, @values) = @$row;
    $owners{$owner} = \@values;
}
close $fh;

my $key = 'Y65';
my $index = 1;
say "Passing count for $key = ", $owners{$key}->[$index];

【讨论】:

  • @hakonhagland 感谢您的指导。在实现您的代码时,我得到输出“在 table.pl 第 78 行中使用未初始化的值。为 Y65 传递计数 =”在这种情况下,第 78 行是代码的最后一行。我一直在尝试调整它,但我无法让它仍然工作。非常感谢您迄今为止的指导。
  • 你应该使用:encoding(UTF-8)而不是:utf8
  • @FranceMadrid 由于第 78 行是最后一行,警告 "Use of uninitialized value in say at table.pl line 78" 表示$key,@987654328 @,或者很可能 $owners{$key} 是未定义的。我的猜测是密钥$key 不存在于哈希%owners 中。你可以通过使用例如检查吗? Data::Dumper 在哈希上?
【解决方案2】:

由于不清楚“将 CSV 文件加载到 perl 哈希”是什么意思(这也没有任何意义。一个哈希数组,每行一个,也许,如果你不关心保持顺序字段,但只是一个哈希?键应该是什么?),让我们特别关注您的问题的其余部分

我将如何打印“所有者”Y65 的“通过”计数。

还有一些其他 CSV 模块可能比Text::CSV 更易于使用:

  • Tie::CSV_File 允许您访问 CSV 文件,如二维数组。 $foo[0][0] 是绑定文件第一行的第一个字段。

所以:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use Tie::CSV_File;

my $csv = "data.csv";
tie my @data, "Tie::CSV_File", $csv or die "Unable to tie $csv!";
for my $row (@data) {
  say $row->[2] and last if $row->[0] eq "Y65";
}
  • DBD::CSV 让您可以将 CSV 文件视为数据库中可以运行 SQL 查询的表。

所以:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use DBI;

my $csv = "data.csv";
my $dbh = DBI->connect("dbi:CSV:", undef, undef,
                       { csv_tables => { data => { f_file => $csv } } })
  or die $DBI::errstr;
my $owner = "Y65";
my $p = $dbh->selectrow_arrayref("SELECT Passing FROM data WHERE Owner = ?",
                                 {}, $owner);
say $p->[0] if defined $p;

所以:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use Text::AutoCSV;

my $csv = "data.csv";
my $acsv = Text::AutoCSV->new(in_file => $csv) or die "Unable to open $csv!";
my $row = $acsv->search_1hr("OWNER", "Y65");
say $row->{"PASSING"} if defined $row;

最后一个可能最接近我认为你想要的。

【讨论】:

    猜你喜欢
    • 2010-09-19
    • 2015-07-06
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2015-07-07
    • 2015-12-03
    相关资源
    最近更新 更多