use CGI; my $cgi = CGI->new( 'a.b.c=3&a.b.c=4&x.y=4' ); my $args = {}; my @names = $cgi->param; foreach my $name (@names) { my $p = $args; my @keys = split /\./, $name; for my $i (0 .. $#keys-1) { $p = $p->{$keys[$i]} ||= {}; } my @values = $cgi->param($name); $p->{$keys[-1]} = @values==1 ? $values[0] : \@values; } use Data::Dumper; $Data::Dumper::Indent = 1; print Dumper $args; #### $VAR1 = { 'x' => { 'y' => '4' }, 'a' => { 'b' => { 'c' => [ '3', '4' ] } } };