use strict; use warnings; use Data::Dumper; my %desc = ( 200 => { type => 'single', names => [ 'f1', 'f2', 'f3', 'name', 'street', 'place1', 'place2', 'f8', 'f9', 'f10', 'f11', 'email', 'f13' ] }, 501 => { type => 'single', names => [ 'rate1', 'rate2' ] }, 530 => { type => 'multiple', names => [ 'f1', 'f2', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9' ] } ); my %data; $/ = "`\n"; foreach my $line () { chomp $line; my @fields = split '~\d\d', $line; next unless length $line; next unless scalar(@fields); my $fieldno = shift @fields; if( exists $desc{$fieldno} ) { if( $desc{$fieldno}{type} eq 'single' ) { @{$data{$fieldno}}{ @{ $desc{$fieldno}{names} } } = @fields; } else { push @{ $data{$fieldno} }, {}; @{ $data{$fieldno}[-1] }{ @{$desc{$fieldno}{names}} } = @fields; } } else { print "Unknown data $fieldno\n"; } } print Dumper \%data; __DATA__ 200~020000000123~0509112013~0610102013~07JOHN SMITH~08131 MAIN ST~09SOMEWHERE TX 77777~12SOMEWHERE~13TX~1477777~15R011~197~24bobsmithsemail@gmail.com~251` 501~0211.150%~03.030547%` 500~0109112013~020001~03PERSONAL LOAN~05Balance Forward~0694188~0770~087~182~21Original Balance~22138000~24608` 300~01BOBS FRIEND~021` 530~0109182013~0209182013~0312184-~04609~051237~0610338-~0783850~08Payments by Check~23K~25P` 510~0109182013~0209182013~03Mail Transaction~041` 539` 530~0110082013~0210082013~0312200-~05512~0611688-~0772162~08Payments by Check~23K~25P` 510~0110082013~0210082013~03Mail Transaction~041` 539` 599~0110102013~02Ending Balance~0372162~10Total Aggregate Amount Paid From Open~12Total Interest Paid From Open~136063~141218~1565838` 570~0112183~0311042013~0411042013~0512162~0712162~0844~1112183` 540~012~0224384` 550~01Interest Paid~026063~031218~06609~071749~0865838~091218` 690~010004~032219~04600` 701~01PERSONAL LOAN~0272162`