use strict; use warnings; use Data::Dumper; my %result = (key1 => undef, key2 => undef, key3 => undef); { # So that the effect of local is limited to that block local $/ = 'ENDKEY'; while( my $line = ) # in your case { next unless $line =~ mx; my $key = $1; next unless exists $result{$key}; $result{$key} = { attrib1 => 'null', attribmsg => 'null' }; while ($line =~ m<\s+ (attrib1 | attribmsg) :.*? = \s+ (\w+) >gx) { $result{$key}{$1} = $2; } } } print Dumper \%result; __DATA__ HIT key1 so start to process attrib1: base = FULL attribmsg: middle = MEDIUM ENDKEY HIT key2 so start to process attrib1: base = FULL ENDKEY HIT key9 so start to process attrib1: base = FULL ENDKEY