use Text::CSV_XS "csv"; my %sums; # Column sums. $sum{column} += $value my @head; my @pats; csv (in => "input.csv", out => undef, bom => 1, kh => \@head, on_in => sub { my ($csv, $row) = @_; unless (@pats) { # Fetch the "patN" column names, in order. This works # for single digit "patN" names, as that was your # example. Multi-digit names will require a more complex # sort, left as an exercise to the reader. # XXX @pats = sort { grep m/^pat\d+$/ } @head; @pats = sort grep m/^pat\d+$/ => @head; # This line fixed } for (@{$row}{@pats}) { # You are now iterating over every patN value, # in order. Perform your transformation } # Just an example. $sums{$_} += $row->{$_} for @pats; });