my $data = {}; while () { chomp; my @fields = split /\s*[=\.]\s*/; build( $data, \@fields, pop @fields ); } sub build { my ($ref, $path, $val) = @_; return $val unless @$path; my $el = shift @$path; if ($el=~/^\[(\d+)\]$/) { $ref->[$1] = build( $ref->[$1], $path, $val ) } else { $ref->{$el} = build( $ref->{$el}, $path, $val ) } return $ref; } __DATA__ object.prop.subprop.[0].name = foo object.prop.subprop.[1].name = bar obj.prop.[0] = blah obj.prop.[1] = 1000 #### { obj => { prop => ["blah", 1000] }, object => { prop => { subprop => [{ name => "foo" }, { name => "bar" }] } }, } #### sub dive { my ($ref,@path) = @_; return $ref unless @path; my $el = shift @path; if ($el=~/^\[(\d+)\]$/) { return dive( $ref->[$1], @path ) } else { return dive( $ref->{$el}, @path ) } } print dive( $data, qw/ obj prop [0] / ), "\n"; # prints "blah" print dive( $data, qw/ object prop subprop [1] name / ), "\n"; # prints "bar"