 <p><a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it" rel="nofollow">TIMTOWTDI</a></p> <pre><code>#!/usr/bin/perl use strict; use warnings; my $file = "list.csv"; # Use lexical filehandles, not globals; use 3-arg open; don't quote filename open ( my $fh, '&lt;', $file ) or die "Can't open file: $!\n"; my( @lines ) = &lt;$fh&gt;; close( $fh ); # split takes a regex; also, notice the shift my @headers = split( /,/, shift @lines ); my %hash; # Use perly for loops here foreach my $i ( 0..$#lines ) # This works, too #for my $i ( 0..$#lines ) { # split takes a regex my @strings = split( /,/, $lines[$i] ); # One way (probably best) @{ $hash{$i} }{ @headers } = @strings; # Another way #$hash{$i} = { map { $headers[$_] =&gt; $strings[$_] } ( 0 .. $#strings ) }; # Another way #$hash{$i}{ $headers[$_] } = $strings[$_] = for(0..$#strings); } #use Data::Dumper; #print Dumper \%hash; </code></pre> <p>But yes, using <a href="http://p3rl.org/Text%3a%3aCSV" rel="nofollow">Text::CSV</a> (or the faster <a href="http://p3rl.org/Text%3a%3aCSV_XS" rel="nofollow">Text::CSV_XS</a>) would be even better than trying to manually split the CSV yourself (what happens if there are spaces? what happens if the fields and/or headers are quoted? It's a solved problem.)</p>