tags:

views:

104

answers:

4

Hi All,

I wrote a perl script using Tie::Handle::CSV to process a bunch of data in a csv file and print out only what I need into a new csv file. Right now, I print out the header line with all of the field names by just a hardcoding it in like so:

print '"TERM", "STUDENT ID", "NAME", ..."'."\n";

I suspect this is a dumb way of doing this, but I don't know how to get access to the header from within the Tie::Handle::CSV object. It's instantiated like so,

my $fh = Tie::Handle::CSV->new($file,header=> 1);

and data is accessed like so,

$line -> {'CATALOG_NBR'}

I know enough to know this is a hash-reference, but not enough to know how to print the header using this rather than hardcoding it. Obviously, "they" usually change the precise column names and ordering just after I get the script working again each term.

Thanks a lot for any help! JA

+1  A: 

According to the documentation, it looks like turning off header => 1 in your constructor will cause it to not parse the header. You should then get the header column names as the first $line returned from the object.

It also means that your $lines will be array references rather than hash references, so you'll need to print out positional values with $line->[0], $line->[1], and so on, instead of using the header names.

If you want to use the header => 1 option, you can get the hash keys with my @headers = keys %{ $line }. Note that there's no guarantee that the keys will be in any particular order, so you'd have to figure out a way to order them yourself.

I haven't actually used this module, so this is all conjecture based on reading the documentation for the header option.

friedo
Thanks guys - I ended up doing essentially a combination of your advice. I opened two file handles - the second one $hfh with with header=>0 so I could print the header labels in the correct order like so: my $fh = Tie::Handle::CSV->new($file, header => 1); my $hfh = Tie::Handle::CSV->new($file, header=>0); my $line = <$hfh>; my $header; foreach(@{$line}) { $header .= "\"$_\","; } print "$header\n"; Thanks again for your assistance!
Jason
+2  A: 

If header is defined and not an array reference, then the first line of the document will be used as header. Sadly, there is no method to get such header as originally was, so short of reading the first line using the header option as false, storing it (it is already an array ref) and closing the file and rereading again, I don't see an easier way to do it.

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

my $csv_fh = Tie::Handle::CSV->new('basic.csv', header => 0);
my $header = <$csv_fh>;
close $csv_fh;
print join(',', @$header), "\n";

$csv_fh = Tie::Handle::CSV->new('basic.csv', header => 1);
while (my $csv_line = <$csv_fh>) {
    # $csv_line can be used here
    ...
}
close $csv_fh;
Leonardo Herrera
Thanks guys - I ended up doing essentially a combination of your advice. I opened two file handles - the second one $hfh with with header=>0 so I could print the header labels in the correct order like so: my $fh = Tie::Handle::CSV->new($file, header => 1); my $hfh = Tie::Handle::CSV->new($file, header=>0); my $line = <$hfh>; my $header; foreach(@{$line}) { $header .= "\"$_\","; } print "$header\n"; Thanks again for your assistance!
Jason
A: 

Thanks guys - I ended up doing essentially a combination of your advice. I opened two file handles - the second one $hfh with with header=>0 so I could print the header labels in the correct order like so:

my $fh = Tie::Handle::CSV->new($file,  header => 1);
my $hfh = Tie::Handle::CSV->new($file, header=>0);
my $line = <$hfh>;
my $header;
foreach(@{$line}) {
  $header .= "\"$_\",";
}
print "$header\n";

Thanks again for your assistance!

Jason
+2  A: 

Hi Jason,

A bit late to the party, but I just released a new version of Tie::Handle::CSV (should be up on CPAN in a few hours). It adds support for a header() method, which returns a CSV formatted header. Usage might look like:

   my $fh = Tie::Handle::CSV->new( $file, header => 1 );
   print $fh->header;

Hope this helps,

  • danboo
danboo
That's fantastic! Thanks very much - it works like a charm. I appreciate this very much - Jason
Jason