如何根据列名从CSV文件中过滤列

时间:2018-10-04 17:32:54

标签: perl csv

我正在使用如下所示的CSV数据。我不想使用csv文件中的用户名和时间戳。我可能会添加几列或删除几列。

我在Text CSV中找不到任何合适的方法。 请让我知道是否有任何方法或模块

UniqueId, Name, description, user,timestamp     
1,jana,testing,janardar,12-10-2018:00:
sub _filter_common_columns_from_csv{

    my $csvfile = shift;
    my $CSV = Text::CSV_XS->new(
                                {
                                    binary => 1,
                                    auto_diag => 3,
                                    allow_quotes => 0,
                                    eol => $/ 
                                });
    my $_columns ||= do {
    open(my $fh, '<', $csvfile) or die $!;
    my @cols = @{ $CSV->getline($fh) };
    close $fh or die $!;
    for (@cols) { s/^\s+//; s/\s+$//; }
        \@cols;
    };
    my @columns = @{ $_columns };     
    my %deleted;                        
    my @regexes = qw(user timestamp);
    foreach my $regex (@regexes) {
            foreach my $i (0 .. ($#columns - 1)) {
                    my $col = $columns[$i];
                       $deleted{$i} = $col if $col =~ /$regex/;
            }
    }

    my @wanted_columns = grep { !$deleted{$_} } 0 .. $#columns - 1;
    my $input_temp = "$ENV{HOME}/output/temp_test.csv";


    open my $tem, ">",$input_temp or die "$input_temp: $!";

    open(my $fh, '<', $csvfile) or die $!;

    while (my $row = $CSV->getline($fh)) {
           my @fields = @$row;
              $CSV->print($tem, [ @fields[@wanted_columns] ]) or $CSV->error_diag;
    }
    close $fh or die $!;
    close $tem or die $!;

    return $input_temp;
}

3 个答案:

答案 0 :(得分:2)

请参见getline_hr

use warnings;
use strict;
use feature 'say';

use List::MoreUtils qw(any);
use Text::CSV;

my $file = shift @ARGV || die "Usage: $0 filename\n";

my @exclude_cols = qw(user timestamp);

my $csv = Text::CSV->new ( { binary => 1 } ) 
    or die "Cannot use CSV: ".Text::CSV->error_diag (); 

open my $fh, '<', $file or die "Can't open $file: $!";

my @cols  = @{ $csv->getline($fh) };

my @wanted_cols = grep { 
    my $name = $_; 
    not any { $name eq $_ } @exclude_cols;
} @cols;

my $row = {}; 
$csv->bind_columns (\@{$row}{@cols});

while ($csv->getline($fh)) {
    my @wanted_fields = @$row{ @wanted_cols };
    say "@wanted_fields";
}

语法@$row{@wanted_cols}用于哈希值slice,该哈希值从hashref @wanted_cols返回$row中键的值列表。

答案 1 :(得分:0)

使用Text :: AutoCSV从任意CSV文件中删除给定命名列的实际示例,例如在您发布的代码中(比仅编写特定列的文档示例更复杂):

    class B : public A {
      public:
        void start(){
            boost::spawn(io_service, [this](boost::asio::yield_context yield) 
          {  
             // work
            });
         }

    }
    class C: public A {
         public: 
         void start(){
            boost::spawn(io_service, [this](boost::asio::yield_context yield) 
          {  
             // work
            });
         }
    }
    do_work() {
       auto object = A::getInstance(); // this returns boost::shared_ptr and it does not store that instance
       object->start();

    }

  class A {
  public:
      virtual void start () =0;  
      static boost::shared_ptr<A> getInstance() {
       return boost::shared_ptr<A>(new B());
     }

   }

答案 2 :(得分:0)

如果您也想以其他方式修改CSV,并且如果SQL可以方便地进行修改,请考虑使用DBD::CSV

然后可以在CSV文件上打开数据库句柄,使用SELECT查询选择所需的列,并使用Text::CSVText::CSV_XS写入结果。

有关更多详细信息,请参见the DBD::CSV documentation或例如this simple wrapper script for querying CSV files