use strict; use warnings; use Data::Dumper; my $s = <<'END'; sys ecm cloud-provider /Common/aws-ec2 { description "The aws-ec2 parameters" property-template { account { } availability-zone { valid-values { a b c d } } instance-type { valid-values { t2.micro t2.small t2.medium } } region { valid-values { us-east-1 us-west-1 } } } } END my %valid_keys = map { $_, 1 } qw/ description property-template account availability-zone instance-type valid-values region /; $s =~ s/ (?| "([^"{}]+)" | (?:^|(?<=\s)) ([^\s{}]+) (?:$|(?=\s)) ) /"$1"/xg; $s =~ s/("|})\s\K/,/g; $s =~ tr/{}/[]/; print Dumper fix_aref([ eval $s ]); sub fix_aref { my $aref = shift; ref and $_ = fix_aref($_) for @$aref; return $aref unless $#$aref % 2; for ( 0 .. $#$aref ) { next if $_ % 2; return $aref unless exists $valid_keys{ ${$aref}[$_] } } return +{ @$aref } }