无法在Perl中使用Text :: CSV_XS从.csv中读取多个列 [英] Unable to read multiple columns from a .csv using Text::CSV_XS in Perl

查看:78
本文介绍了无法在Perl中使用Text :: CSV_XS从.csv中读取多个列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个脚本,该脚本会将(不太大的).csv中的数据列分成单独的列表,以供以后使用

I'm trying to write a script that will separate out columns of data from a (not terribly large) .csv into individual lists for use later using the Text::CSV_XS library. I have no problem getting individual columns, but I seem to be unable to iterate through a list of columns using a foreach loop.

#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
use 5.18.2;

my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1 });
open my $fh, "<", "/users/whoever/test_csv.csv" or die "$!";

sub column_grabber {
        foreach my $column (@_) {
                my @data = map { $_->[$column] } @{$csv->getline_all ($fh)};
                return @data;
        }
}

my @column_numbers = (1,2,3,4);

my @collected_data = column_grabber(@column_numbers);

close $fh or die "$!";

调用此子例程以获取列列表,按预期,仅给我该列表的第一列,但列表中随后的列均不给我.进行一些故障排除后,表明@_正在查看我通过的整个列表.

Calling this subroutine for a list of columns gives me only the first column of the list as anticipated, but none of the following columns from the list. A bit of troubleshooting shows that @_ is seeing the entire list I pass.

通过省略return语句,foreach循环会传递@ids中传递的所有列,但我不会从@data获得任何输出.

By omitting the return statement, the foreach loop carries through all of the columns passed in @ids, but I get no output from @data.

循环中是否存在一些我不解释的行为?也许与map()语句有关?

Is there some behavior in the loop I'm not accounting for? Perhaps it has something to do with the map() statement?

所以在解决了一段时间并重新考虑了一些问题之后,我已经解决了我的问题.

So after playing around with this for a while and rethinking things a bit, I've solved my problem.

  • 首先,从循环内部打开和关闭文件句柄似乎有消除了很多头痛.
  • 第二,只需解析 @column_numbers 子例程,然后将标量传递给& column_grabber .这样可以节省当我真的不需要时,我就从迷茫的参考书中迷失了自己担心这个小脚本.
  • First, opening and closing the filehandle from inside the loop seems to have cleared up a lot of headaches.
  • Second, it's a lot easier to just parse @column_numbers outside the subroutine and pass scalars to &column_grabber instead. This saves me from getting lost in a sea of references when I don't really need to worry about it for this small script.

所以现在我的运行脚本如下:

So now my functioning script looks like this:

#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
use 5.18.2;

sub column_grabber {
    my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1 });
    open my $fh, "<", "/users/whoever/test_csv.csv" or die "$!";

    my $column = shift @_;
    my @data = map { $_->[$column] } @{$csv->getline_all ($fh)};
    return @data;

    close $fh or die "$!";
}

my @column_numbers = (1,2,3,4);
foreach my $column(@column_numbers){
    my @collected_data = &column_grabber($column);
...
}

感谢评论者的投入和帮助.

Thanks for the input and help from commenters.

推荐答案

请记住, @data 的每个元素(因此已重命名为 @rows $行)应该是对所选字段数组的引用.

Keep in mind that each element of @data (hereby renamed @rows or $rows) should be a reference to an array of the selected fields.

my @rows;
while ( my $row = $csv->getline($fh) ) {
   push @rows, [ @{ $row }[@column_numbers] ];
}

my $rows = $csv->getline_all($fh);
@_ = @{ $_ }[@column_numbers] for @$rows;

my @rows = map { [ @{ $_ }[@column_numbers] ] } @{ $csv->getline_all($fh) };

这篇关于无法在Perl中使用Text :: CSV_XS从.csv中读取多个列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆