Perl-从CSV文件中读取特定行

Perl-从CSV文件中读取特定行,perl,csv,text-parsing,Perl,Csv,Text Parsing,我希望从一个.csv文件中读取一个特定的“类别”,该文件如下所示: Category 1, header1, header2, header3,..., , data, data, data,..., , data, data, data,..., , data, data, data,..., Category 2, header1, header2, header3,..., , data, data, data

我希望从一个.csv文件中读取一个特定的“类别”,该文件如下所示:

Category 1, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...,
Category 2, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...,
Category 3, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...
假设我只想打印特定“类别”中的数据。。。我该怎么做呢

ie:我想打印类别2数据,输出应如下所示:

Category 2, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...

除非您的数据包含带引号的字段,如
a、b、c、“复杂字段,带引号”、e、f、g
,否则使用
Text::CSV
比使用简单的
split/,/
没有任何优势

本例将数据分类为一个可以简单直接访问的散列。我使用了
Data::Dump
仅显示结果数据结构的内容

use strict;
use warnings;
use autodie;

open my $fh, '<', 'mydata.csv';

my $category;
my %data;
while (<$fh>) {
  chomp;
  my @data = split /,/;
  my $cat = shift @data;
  $category = $cat if $cat =~ /\S/;
  push @{ $data{$category} }, \@data;
}

use Data::Dumper;
$Data::Dumper::Useqq = 1;
print Dumper \%data;

更新

如果您只想分隔文件的给定部分,则无需将其放入散列。这个程序会做你想做的

#!/usr/bin/perl

use strict;
use warnings;
use autodie;

my ($file, $wanted) = @ARGV;

open my $fh, '<', $file;

my $category;

while (<$fh>) {
  my ($cat) = /\A([^,]*)/;
  $category = $cat if $cat =~ /\S/;
  print if $category eq $wanted;
}
输出

{
  "Category 1" => [
                    [" header1", " header2", " header3", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                  ],
  "Category 2" => [
                    [" header1", " header2", " header3", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                  ],
  "Category 3" => [
                    [" header1", " header2", " header3", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                    [" data", " data", " data", "..."],
                  ],
}
Category 2, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...

如果该输出确实是您想要的,那么您可以使用perl one liner:

perl -ne "$p = 0 if /^Category/;$p = 1 if /^Category 2/;print if $p;" myfile.csv

看一看我忘了提;我无法在工作中下载模块/源代码…您可以尝试自己实现一个简单的模块/源代码,但下面是一些原因,说明这是个坏主意:@user3707618:然后在家中下载并在闪存驱动器上使用!这看起来是我需要的,我现在就给它打一针。。谢谢有没有不使用data::Dump打印数据的方法?我已将代码改为使用
data::Dumper
。它是一个核心模块,是Perl标准安装的一部分,因此不需要安装。但是,它不会产生像
Data::Dump
这样的整洁结果。。。如何将特定类别打印到输出文件?好的,我添加了另一个解决方案,它只选择您在命令行上指定的单个类别。为什么?当点击SOL的“类别”时,它会关闭打印,但如果点击“类别2”,它会重新打开打印。(抱歉-在编辑中添加代码时遇到问题)哦,我明白了,我的错。。这不会一直打印到“类别3”吗?不,它将继续打印,直到它碰到字符串“Category”而不是“Category 2”,所以当它碰到“Category 3”时,它停止打印。啊。。。我今天好像很慢
perl -ne "$p = 0 if /^Category/;$p = 1 if /^Category 2/;print if $p;" myfile.csv