use strict; my %profiles; { my $id; while() { if (my $count = ((($id) = /^profile\s+(.*?)\s*$/) .. /^END/)) { unless($count == 1 || $count =~ /E/) { # not first or last line in group /^(\S+)\s+(.*?)\s*$/ and $profiles{$id}{$1} = $2; } } } } use Data::Dumper; print Dumper \%profiles; __DATA__ ... (data as in the root post follows)