use strict; use warnings; my $file = "/path/to/config/config.txt"; my(%by_name, %by_fruit, %by_path); for my $data (parse_file($file)) { # Create lookups for each data item returned. # We assume any data can appear more than once, so we # store an array(ref) of data structures for each match. push @{ $by_name{$data->{name}} }, $data; push @{ $by_fruit{$data->{fruit}} }, $data; push @{ $by_path{$data->{path}} }, $data; } # now let us show all the paths by fruit: for my $fruit (sort keys %by_fruit) { print "Fruit $fruit:\n"; # $by_fruit{$fruit} is now an arrayref of data structures # matching 'fruit eq $fruit' for my $data (@{ $by_fruit{$fruit} }) { print " $data->{path}\n"; } } # Return a list of data structures, one for each line of # the specified file that contains data. # Blank lines and comment lines are ignored. sub parse_file { my $file = shift; open(my $fh, "<", $file) or die "Can't open < $file: $!"; return map { if (/^#/ || /^\s*$/) { (); # no data on this line } else { my($name, $fruit, $path) = split ' ', $_; # Return a data structure as a hash reference { name => $name, fruit => $fruit, path => $path, }; } } <$fh>; # Note that $file is automatically closed when the variable # goes out of scope, on return from this function. }