Home > database >  Perl CSV Parsing with Header Access - header on row 3 and only some rows instead of all rows
Perl CSV Parsing with Header Access - header on row 3 and only some rows instead of all rows

Time:07-09

I am trying to parse a given CSV File, stream on regular base.

My requirement is to Access the Data via ColumName (Header). The ColumNames are not given in row 1. The ColumNames are given in row 2. The CSV does have 100 rows but I only need 2 data rows to import. The separator is a tab.

The following script works for header at row 1 and for all rows in the file I failed to modify it to header at row 2 and to use only 2 rows or a number of rows.

script:

#!/usr/bin/perl
use strict;
use warnings;
use Tie::Handle::CSV;
use Data::Dumper;





my $file = "data.csv";
my $fh = Tie::Handle::CSV->new ($file, header => 1, sep_char => "\t");
my $hfh = Tie::Handle::CSV->new ($file, header => 0, sep_char => "\t");

my $line = <$hfh>;
my $myheader;


while (my $csv_line = <$fh>)
{

        foreach(@{$line}) 
        {
                if ( $_ ne "" )
                {
                        print $_ . "=" .   $csv_line->{$_} . "\n" ;
                }
        }


}

The Data.csv could look like:

This is a silly sentence on the first line
Name    GivenName   Birthdate   Number
Meier   hans    18.03.1999  1
Frank   Thomas  27.1.1974   2
Karl    Franz   1.1.2000    3
Here could be something silly again

Thanks for any hint.

best regards

CodePudding user response:

Use Text::CSV_XS instead of Tie::Handle::CSV (Which depends on the module so you have it installed already), read and throw away the first line, use the second line to set column names, and then read the rest of the data:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Text::CSV_XS;

my $csv = Text::CSV_XS->new({ sep => ",", # Using CSV because TSV doesn't play well with SO formatting
                              binary => 1});

# Read and discard the first line
$_ = <DATA>;

# Use the next line as the header and set column names
$csv->column_names($csv->getline(*DATA));

# Read some rows and access columns by name instead of position
my $nr = 0;
while (my $record = $csv->getline_hr(*DATA)) {
    last if   $nr == 4;
    say "Row $nr: $record->{GivenName} was born on $record->{Birthdate}";
}

__DATA__
This is a silly sentence on the first line
Name,GivenName,Birthdate,Number
Meier,hans,18.03.1999,1
Frank,Thomas,27.1.1974,2
Karl,Franz,1.1.2000,3
Here could be something silly again

CodePudding user response:

Tie::Handle::CSV accepts a filehandle instead of a filename. You can skip the first line by reading one line from it before you pass the filehandle to Tie::Handle::CSV:

use strict;
use warnings;
use Tie::Handle::CSV;
use Data::Dumper;

my $file = "data.csv";

open (my $infile, '<',$file) or die "can't open file $file: $!\n";
<$infile>; # skip first line
my $hfh = Tie::Handle::CSV->new ($infile, header => 1, sep_char => "\t");

my @csv;
my $num_lines = 3;
while ($num_lines--){
    my $line = <$hfh>;
    push @csv, $line;
}
print Dumper \@csv;
  • Related