如何根据列的名称筛选 CSV 文件中的列

  • 本文关键字:CSV 文件 筛选 何根 perl csv
  • 更新时间 :
  • 英文 :


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

我在文本 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;
}

请参阅getline_hr

use warnings;
use strict;
use feature 'say';
use List::MoreUtils qw(any);
use Text::CSV;
my $file = shift @ARGV || die "Usage: $0 filenamen";
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}适用于哈希切片,它从 hashref$row返回@wanted_cols中的键的值列表。

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

#!/usr/bin/perl
use warnings;
use strict;
use Text::AutoCSV qw/remove_accents/;
sub remove_columns {
my ($infile, $outfile, $drop) = @_;
my $csv = Text::AutoCSV->new(in_file => $infile, out_file => $outfile);
# Normalize column names the same way that Text::AutoCSV does
my %drops = map { my $h = remove_accents $_;
$h =~ s/[^[:alnum:]_]//gi;
$h = uc $h;
$h => 1 } @$drop;
my @cols = grep { not exists $drops{$_} } $csv->get_fields_names;
# Hack to avoid reading the file twice.
$csv->{out_fields} = @cols;
$csv->write();
}
remove_columns "in.csv", "out.csv", [ "user", "timestamp" ];

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

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

有关更多详细信息,请参阅 DBD::CSV 文档或例如用于查询 CSV 文件的简单包装脚本。

最新更新