Search code examples
perlcsvhash

Perl CSV to hash


I have a CSV file that contains comment text prior to the header row and data, which I would like to read in as a hash for further manipulation. The primary key have the hash will be a combination of two data values. How do I?

  1. Search for the header row using pattern 'index'
  2. Use header for keys
  3. Read in rest of file.

Example CSV

#
#
#
#
Description information of source of file.

index,label,bit,desc,mnemonic
6,370,11,three,THRE
9,240,23,four,FOR
11,120,n/a,five,FIV

Example desired hash

( '37011' => { 'index' => '6', 'label' => '370', 'bit' => '11', 'desc' => 'three', 'mnemonic' => 'THRE'}, '24023' => {'index' => '9', 'label'  => '240', 'bit' => '23', 'desc' => 'four', 'mnemonic' => 'FOR'}, '120n/a' => {'index' => '11', 'label'  => '120', 'bit' => 'n/a', 'desc' => 'five', 'mnemonic' => 'FIV'} )   

Solution

  • You'll need the Text::CSV module for that:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use Data::Dumper;
    use Text::CSV;
    
    my $filename = 'test.csv';
    
    # watch out the encoding!
    open(my $fh, '<:utf8', $filename)
        or die "Can't open $filename: $!";
    
    # skip to the header
    my $header = '';
    while (<$fh>) {
        if (/^index,/x) {
            $header = $_;
            last;
        }
    }
    
    my $csv = Text::CSV->new
        or die "Text::CSV error: " . Text::CSV->error_diag;
    
    # define column names    
    $csv->parse($header);
    $csv->column_names([$csv->fields]);
    
    # parse the rest
    while (my $row = $csv->getline_hr($fh)) {
        my $pkey = $row->{label} . $row->{bit};
        print Dumper { $pkey => $row };
    }
    
    $csv->eof or $csv->error_diag;
    close $fh;