use strict; use warnings; use Data::Dumper; my @extract; while(){ if /^\.EON/ or /^\s*$/; push @extract, {name => $1} and next if /^\$ NAME : (\w+)/; ${$extract[-1]}{$1} = $2 if /(\S+)\s*(.*)/; } my %result = map { delete $_->{name} => $_ } @extract; print Dumper \%result; __DATA__ $ NAME : corry $$.Inc s d $$.Oc s $$.TO G1 ty n1 EE EE M T1 T2 $$SRU G2 n1 y OO OO M T3 T4 $$SRU .EON $ NAME : patrick $$.Inc c d $$.Oc c $$.TO G1 td n3 EE EE M T5 T6 $$SRU G2 n3 y OO OO M T7 T8 $$SRU .EON $ NAME : sandy $$.Inc k l $$.Oc l $$.TO G1 td n3 FF FF M R5 R6 $$SRU G2 n3 y OO OO N R7 R8 $$SRU .EON