【问题标题】:new to Perl - CSV - find a string and print all numbers in that columnPerl 新手 - CSV - 查找字符串并打印该列中的所有数字
【发布时间】:2013-01-23 11:27:49
【问题描述】:

我在一个 CSV 文件中有一堆数据,第一行是所有字符串(所有文本和下划线),所有后续行都填充了与所述字符串相关的数字。

我试图解析第一行并找到特定的字符串,记住该字符串所在的列,然后遍历文件的其余部分并获取同一列中的数据。我需要对三个字符串执行此操作。

我一直在使用 Text::CSV 但我无法弄清楚如何让它增加一个计数器,直到它在第一行找到字符串然后转到下一行,从相同的获取数据列等。这是我迄今为止尝试过的:

while (<CSV>) {
    if ($csv->parse($data)) {
        my @field = $csv->fields;
        my $count = 0;
            for $column (@field) {
            print ++$count, " => ", $column, "\n";
        }
    } else {
        my $err = $csv->error_input;
        print "Failed to parse line: $err";
    }
}

由于 $data 在第 1 行,它会打印 25 次“1 $data”(CSV 文件中的行数)。我如何让它记住它在哪一列中找到了 $data?另外,因为我知道所有字符串都在第 1 行,我如何让它只解析第 1 行,找到 @data 中的所有字符串,然后解析文件的其余部分,从必要的列并将其放入矩阵或数组数组中?
感谢您的帮助!

编辑:我意识到我的问题措辞有点糟糕。我不知道如何从 CSV 获取列号。这是怎么做到的?
另外,一旦我得到了列号,我如何告诉它 CSV 遍历后续行并仅从该列中获取数据?

【问题讨论】:

  • "我如何让它记住它在哪个列中找到了$data?"将其存储在一个变量中(您在 while 循环之外定义)。
  • 问题措辞不佳,抱歉。在变量中存储一些东西不是问题 - 我如何首先获得列号?
  • 找出你的元素所在的@fields的索引。循环就足够了(尽管有更多惯用的方式)。
  • 这就是我要问的怎么做...我不知道如何找到找到 $data 的@fields 的索引。
  • 循环通过0..$#fields 并设置$_ 等于您选择的索引变量,如果$data 匹配。

标签: perl csv


【解决方案1】:

试试这样的:

use strict;
use warnings;
use Text::CSV;

my $csv = Text::CSV->new({binary=>1});

my $thing_to_match = "blah";
my $matched_index;
my @stored_data = ();

while(my $row= $csv->getline(*DATA)) #grabs lines below __DATA__ 
                                     #(near the end of the script)
{
    my @fields = @$row;

    #If we haven't found the matched index, yet, search for it.
    if(not defined $matched_index)
    {
        foreach my $i(0..$#fields)
        {
            $matched_index = $i if($fields[$i] eq $thing_to_match);
        }
    }

    #NOTE: We're pushing a *reference* to an array!
    #Look at perldoc perldata
    push @stored_data,\@fields;
}

die "Column for '$thing_to_match' not found!" unless defined $matched_index;

foreach my $row(@stored_data)
{
    print $row->[$matched_index] . "\n";
}


__DATA__
stuff,more stuff,yet more stuff
"yes, this thing, is one item",blah,blarg
1,2,3

输出是:

more stuff
blah
2

【讨论】:

  • 不要做我的$line = &lt;&gt;; @values = $csv-&gt;parse() ...这对于任何可能包含换行符的 csv 文件都是错误的。见Text::CSV docs
  • @RobertP - 好收获!谢谢。
【解决方案2】:

我没有时间写一个完整的例子,但我写了一个模块可以帮助你做到这一点。 Tie::Array::CSV 使用一些魔法使您的 csv 文件表现得像 Perl 数组中的 arrayrefs。通过这种方式,您可以使用您的 Perl 知识与文件进行交互。

不过要警告一句!我的模块的一个好处是它是读/写的。既然你只想读,注意不要给它赋值!

【讨论】:

    猜你喜欢
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 2011-05-05
    相关资源
    最近更新 更多