my @products; while ( ) { if ( /^Begin Product (.*)/i ) { # We have a product starting line my %hash; $hash{ 'name' } = $1; # get the product name. # I'm guessing on the next 6 lines as to their functions. $hash{ 'description' } = ; $hash{ 'numberline1' } = ; $hash{ 'numberline2' } = ; my $track = ; $hash{ 'tracking' } = ( $track =~ /(Yes|No)/i ); $hash{ 'images' } = ; $hash{ 'producttext' } = ; # Now you have some weirdness to your stuff. Some of # your items have an XML-like structure, some don't. # I'll assuming that if the lines starts with Begin, # it indicates the start of a list of items. Of course, # End Product will end all this. my $line = ; last if ( $line ~= /End Product/ ); if ( $line ~= /^\s*Begin Option (.*)$/ ) { my $name = $1; my @option_list; while ( ) { last if ( /End Option/ ); push @option_list, $_; } $hash{ $name } = \@option_list; } else { # if there is no option, then stick what's in front of the : as the hash name, the rest as it's value my ( $name, $value ) = ( $line ~= /^\s*(.*?):(.*)$/ ); $hash{ $name } = $value; } push @products, \%hash; }