【问题标题】:How to extract multiple columns from a CSV file using Perl如何使用 Perl 从 CSV 文件中提取多列
【发布时间】:2012-02-15 21:55:29
【问题描述】:

我对 Perl 很陌生,希望有人能帮助我解决这个问题。我需要从嵌入逗号的 CSV 文件中提取两列。格式如下所示:

"ID","URL","DATE","XXID","DATE-LONGFORMAT"

我需要提取DATE 列、XXID 列以及紧跟在XXID 之后的列。请注意,每行不一定遵循相同数量的列。

XXID 列包含 2 个字母的前缀,并不总是以相同的字母开头。它几乎可以是 aplhabet 的任何字母。长度始终相同。

最后,一旦提取了这三列,我需要对XXID 列进行排序并计算重复项。

【问题讨论】:

    标签: perl csv


    【解决方案1】:

    我发布了一个名为 Tie::Array::CSV 的模块,它让 Perl 与您的 CSV 作为原生 Perl 嵌套数组进行交互。如果您使用它,您可以使用您的搜索逻辑并应用它,就好像您的数据已经在数组引用数组中一样。看看吧!

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use File::Temp;
    use Tie::Array::CSV;
    use List::MoreUtils qw/first_index/;
    use Data::Dumper;
    
    # this builds a temporary file from DATA
    # normally you would just make $file the filename
    my $file = File::Temp->new;
    print $file <DATA>;
    #########
    
    tie my @csv, 'Tie::Array::CSV', $file;
    
    #find column from data in first row
    my $colnum = first_index { /^\w.{6}$/ } @{$csv[0]};
    print "Using column: $colnum\n";
    
    #extract that column
    my @column = map { $csv[$_][$colnum] } (0..$#csv);
    
    #build a hash of repetitions
    my %reps;
    $reps{$_}++ for @column;
    
    print Dumper \%reps;
    

    【讨论】:

      【解决方案2】:

      这是一个使用 Text::CSV 模块解析 csv 数据的示例脚本。请查阅模块的文档以找到适合您数据的设置。

      #!/usr/bin/perl
      use strict;
      use warnings;
      use Text::CSV;
      
      my $csv = Text::CSV->new({ binary => 1 });
      
      while (my $row = $csv->getline(*DATA)) {
          print "Date: $row->[2]\n";
          print "Col#1: $row->[3]\n";
          print "Col#2: $row->[4]\n";
      }
      

      【讨论】:

        【解决方案3】:

        您肯定希望使用 CPAN 库来解析 CSV,因为您永远不会考虑格式的所有怪癖。

        请看:How can I parse quoted CSV in Perl with a regex?

        请看:How do I efficiently parse a CSV file in Perl?

        但是,对于您提供的特定字符串,这是一个非常幼稚且非惯用的解决方案:

        use strict;
        use warnings;
        
        my $string = '"ID","URL","DATE","XXID","DATE-LONGFORMAT"';
        
        my @words = ();
        my $word = "";
        my $quotec = '"';
        my $quoted = 0;
        
        foreach my $c (split //, $string)
        {
          if ($quoted)
          {
            if ($c eq $quotec)
            {
              $quoted = 0;
              push @words, $word;
              $word = "";
            }
            else
            {
              $word .= $c;
            }
          }
          elsif ($c eq $quotec)
          {
            $quoted = 1;
          }
        }
        
        for (my $i = 0; $i < scalar @words; ++$i)
        {
          print "column " . ($i + 1) . " = $words[$i]\n";
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-21
          • 2021-06-24
          • 2023-03-02
          • 1970-01-01
          • 2011-06-13
          • 1970-01-01
          • 2021-05-22
          相关资源
          最近更新 更多