parse file-1 for every line: remove newline split it using ';' filling an array check if the element 1 (array start from 0) of such array is 'Wood' if yes create a sub key using element zero of the above array and assign as value an anonymous, empty array [] close file-1 parse file-2 for every line: remove newline split it using ';' filling an array if the element 2 is an already present key in the hash push the element 0 into the values of such key (we have defined it as an anonymous array [] above) close file-2 print out the datastructure in the way you like #### # pay attention to windows doublequote around the oneliner, on Linux is perl -e '...' not perl -e ".." perl -MData::Dumper -F";" -lane "BEGIN{$f=1};$f?$hoh{$F[1]}{$F[0]}=[]:push @{$hoh{Wood}{$F[2]}},$F[0];$f=0 if eof; END {print Dumper \%hoh}" file-1.txt file-2.txt $VAR1 = { 'Wood' => { 'NASSAUCOUNTY' => [ '920232', '727659', '471817', '983043', '578286' ], 'SUWANNEECOUNTY' => [ '640802', '403866', '828788', '751490', '972562', '367541', '481360' ], 'CLAYCOUNTY' => [ '119736', '448094', '206893', '333743', '172534', '785275', '995932', '223488', '433512' ] } }; #### # spacing and comments added perl -MO=Deparse -MData::Dumper -F";" -lane "BEGIN{$f=1};$f?$hoh{$F[1]}{$F[0]}=[]:push @{$hoh{Wood}{$F[2]}},$F[0]; $f=0 if eof; END{print Dumper \%hoh}" file-1.txt file-2.txt # B::Deparse translate the above into the below: # the following block is added by the -l switch # automatically handling newlines BEGIN { $/ = "\n"; $\ = "\n"; } use Data::Dumper; # this while block is added by th -n switch (see also -p for completness) LINE: while (defined($_ = )) { chomp $_; # the special @F array (see perlvar) is called into play by the -a (autosplit) switch # (UPDATE) the -F";" switch states that we are going to automatically split using ';' instead of the default (space) our(@F) = split(/;/, $_, 0); # this is our BEGIN block esplicitally put in pur oneliner setting $f = 1 before doing anything # please note the BEGIN blocks are executed as they are seen by the compiler, so even if put inside the while # it is executed only once, as it is seen sub BEGIN { $f = 1; } # our part: the ternary '? :' is ' IF ? THEN : ELSE' # IF $f is true (ie we are processing the first file) $f ? # THEN use @F elements to create a subkey assigning to it an empty anonymous array [] $hoh{$F[1]}{$F[0]} = [] : # ELSE (we are processing the second file) # push into the subkey (that holds an array) the value of the first element push(@{$hoh{'Wood'}{$F[2]};}, $F[0]); # the trick: eof is true when we reach the end of a file: so at the end of file-1 it happens to be true: we trap it and # we change $f to 0 ie we are stating we are processing, from now on, the second (or third) file $f = 0 if eof; # our END block executed only once at the end of program is used to dump the datastructure # it can be conceiled using the 'eskimo operator' trick, I prefere Data::Dump over Data::Dumper sub END { print Dumper(\%hoh); } ; } # B::Deparse tell us the syntax is OK -e syntax OK