use warnings; use strict; use CGI; use Data::Dumper; my $cgi = CGI->new( 'a.b.c=3&d.e.f.g=5&x.y=4' ); my %params=$cgi->Vars(); my %hash; while (my ($param,$value) = each %params ) { my $hashref=fill($param,$value); my $key=(keys %$hashref )[0]; $hash{$key}=$hashref->{$key}; } print Dumper(\%hash); sub fill { my $node=shift; my $value=shift; my @nodetree=split /\./, $node; if (scalar @nodetree == 1) { return { $nodetree[0] => $value } }; my $trunk=shift @nodetree; $node=join ".", @nodetree; return { $trunk => fill($node,$value) }; } __END__ $VAR1 = { 'a' => { 'b' => { 'c' => '3' } }, 'd' => { 'e' => { 'f' => { 'g' => '5' } } }, 'x' => { 'y' => '4' } };