Perl - чтение определенных строк из файла CSV

Я хочу прочитать определенную «категорию» из файла .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,...

Допустим, я хотел напечатать только данные из определенной «категории» ... как мне это сделать?

то есть: я хочу напечатать данные категории 2, результат должен выглядеть так:

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

person andrejr    schedule 04.06.2014    source источник
comment
Взгляните на Text::CSV_XS   -  person Hunter McMillen    schedule 04.06.2014
comment
Я забыл упомянуть; Я не могу скачать модули / исходный код на работе ...   -  person andrejr    schedule 04.06.2014
comment
Вы можете попробовать реализовать простой вариант самостоятельно, но вот несколько причин, по которым это было бы плохой идеей: tburette.github.io/blog/2014/05/25/   -  person Hunter McMillen    schedule 04.06.2014
comment
@ user3707618: Тогда качай дома и забирай на флешку!   -  person Borodin    schedule 04.06.2014


Ответы (2)


Если ваши данные не включают поля в кавычках, например a,b,c,"complicated field, quoted",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;

вывод

{
  "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", "..."],
                  ],
}

Обновить

Если все, что вам нужно, это разделить данный раздел файла, нет необходимости помещать его в хеш. Эта программа сделает то, что вы хотите.

#!/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;
}

Запустите его вот так в командной строке

get_category.pl mydata.csv 'Category 2' > cat2.csv

вывод

Category 2, header1, header2, header3,...,
          , data, data, data,...,
          , data, data, data,...,
          , data, data, data,...
person Borodin    schedule 04.06.2014
comment
Похоже, это то, что мне нужно, я попробую прямо сейчас .. спасибо! - person andrejr; 04.06.2014
comment
Есть ли способ распечатать данные без использования Data :: Dump? - person andrejr; 04.06.2014
comment
Я изменил свой код, чтобы использовать вместо него Data::Dumper. Это базовый модуль, который является частью стандартной установки Perl и поэтому не требует установки. Однако он не дает таких хороших результатов, как Data::Dump. - person Borodin; 04.06.2014
comment
Извините, я новичок в Perl ... Как мне распечатать определенную категорию в выходной файл? - person andrejr; 04.06.2014
comment
Хорошо, я добавил еще одно решение, которое выбирает только одну категорию, которую вы указываете в командной строке. - person Borodin; 04.06.2014

Если этот вывод определенно то, что вам нужно, вы можете сделать это с помощью однострочника perl:

perl -ne "$p = 0 if /^Category/;$p = 1 if /^Category 2/;print if $p;" myfile.csv
person Tom Melly    schedule 04.06.2014
comment
Почему? Он отключает печать, когда попадает в категорию в SOL, но включает ее снова, если она попадает в категорию 2. (извините, возникли проблемы с добавлением кода при редактировании) - person Tom Melly; 04.06.2014
comment
О, я понимаю, моя проблема ... Разве это не продолжит печатать в Категории 3? - person andrejr; 05.06.2014
comment
Нет, печать будет продолжаться до тех пор, пока не будет достигнута строка «Категория», отличная от «Категория 2», поэтому печать прекращается при достижении «Категории 3». - person Tom Melly; 05.06.2014
comment
Ах ... кажется, я сегодня довольно медленный - person andrejr; 05.06.2014