use strict; use warnings; use Parse::RecDescent (); my $grammar = <<'__END_OF_GRAMMAR__'; { use strict; use warnings; sub dequote { local $_ = @_ ? $_[0] : $_; s/^"//; s/"$//; s/\\(.)/$1/sg; return $_; } } parse : record(s?) /\Z/ { [ map @$_, @{$item[1]} ] } record : 'instance' 'of' 'Win32_LogicalDisk' '{' field(s?) '}' ';' { my $name; my %record; %record = map @$_, @{$item[5]}; $name = delete($record{Name}); $name ? [ $name, \%record ] : undef } field : key '=' val ';' { [ $item[1], $item[3] ] } key : IDENT val : QSTRING IDENT : /\w+/ QSTRING : /"(?:[^\\"]|\\.)*"/ { dequote($item[1]) } # guessing. __END_OF_GRAMMAR__ my $p = Parse::RecDescent->new($grammar) or die("Bad grammar\n"); my $text; { local $/; $text = ; } my $data = $p->parse($text) or die("Bad data\n"); require Data::Dumper; print(Data::Dumper::Dumper($data));