#! perl -slw use strict; my %ini; my( $product, $feature ); while( ) { chomp; if( /\s+(\S+)=(\S+)/ ) { $ini{ $product // die "Malformed ini at:$." } { $feature // 'none' } { $1 } = $2; push @{ $ini{ $product }{ $feature // 'none' }{ order } }, $1; } elsif( /^PROD/ ) { push @{ $ini{ $product }{ order } }, 'none' if $product and not exists $ini{ $product }{ order }; $product = $_; push @{ $ini{ order } }, $product; undef $feature; } else { /^\s+(\S+)/ and $feature = $1; push @{ $ini{ $product }{order} }, $feature; } } for my $product ( @{ $ini{ order } } ) { print $product; for my $feature ( @{ $ini{ $product }{ order } } ) { print "\t", $feature if $feature ne 'none'; for my $type ( @{ $ini{ $product }{ $feature }{ order } } ) { print "\t\t$type=$ini{ $product }{ $feature }{ $type }"; } } } __DATA__ PRODUCT1 FEATURE1_PRODUCT1 PROPERTY1_FEATURE1_PRODUCT1=VALUE1 PROPERTY2_FEATURE1_PRODUCT1=VALUE2 PROPERTY3_FEATURE1_PRODUCT1=VALUE3 PRODUCT2 PROPERTY1_PRODUCT2=VALUE1 PROPERTY2_PRODUCT2=VALUE2 PRODUCT3 FEATURE1_PRODUCT3 PROPERTY1_FEATURE1_PRODUCT3=VALUE1 PROPERTY2_FEATURE1_PRODUCT3=VALUE2 PROPERTY3_FEATURE1_PRODUCT3=VALUE3 FEATURE2_PRODUCT3 PROPERTY1_FEATURE1_PRODUCT3=VALUE1 FEATURE3_PRODUCT3 PROPERTY1_FEATURE1_PRODUCT3=VALUE1 PROPERTY2_FEATURE1_PRODUCT3=VALUE2 PROPERTY3_FEATURE1_PRODUCT3=VALUE3 PRODUCT4 PROPERTY1_PRODUCT4=VALUE1 PROPERTY2_PRODUCT4=VALUE2 PRODUCT5