courierb has asked for the wisdom of the Perl Monks concerning the following question:

convert stirng to array of hashes Hi perl monks

I have a string and how could i conert it to array of hashes?
I googled a while and end up in vain. i most of sample teach me convert string to
array by split. but how to turn a "array of hashes" straucture alike sting into a
real array of hashes ?

Many thanks.


turn $string $string = "{file => 'file1', desc => 'test}, {file => 'file12', desc + => 'test2'}" into my @array_of_hashes = ( {file => 'file1', desc => 'test}, {file => 'file12', desc => 'test2'}, );

Replies are listed 'Best First'.
Re: Convert stirng to array of hashes
by cdarke (Prior) on Aug 08, 2009 at 13:20 UTC
    As moritz said, eval is the easiest way, but if you don't wish to take that risk:
    use strict; use warnings; use Data::Dumper; my $string = q({file => 'file1', desc => 'test'}, {file => 'file12', +desc => 'test2'}); my @array_of_hashes; my @hashes = $string =~ /(\{.*?\})/g; for my $hashstr (@hashes) { my @keys = $hashstr =~ /(\w+)\s*=>/g; my @values = $hashstr =~ /=>\s*\'(\w+)\'/g; my %hash; @hash{@keys} = @values; push @array_of_hashes, \%hash; } print Dumper(\@array_of_hashes);
    Gives:
    $VAR1 = [ { 'desc' => 'test', 'file' => 'file1' }, { 'desc' => 'test2', 'file' => 'file12' } ];
      You can also build a parser with TheDamian's Regexp::Grammars. Here is a proof of concept, which you can improve.
      use Regexp::Grammars; my $parser = qr{ (?: <[Hash]> ** ( , ) ) <token: Hash> \{ <[KV]> ** ( , ) \} <token: KV> (?: \s* <[Key]> \s* => \s* <[Value]> \s* ) <token: Key> \w* <token: Value> ' \w* ' }x; use Data::Dumper; # Match the grammar against some text... if ("{ foo => 'bar', baz => 'bof' }, {bing => 'go'}" =~ $parser) { # If successful, the hash %/ will have the hierarchy of results.. +. print Dumper(\%/ ); } __END__ $VAR1 = { '' => '{ foo => \'bar\', baz => \'bof\' }, {bing => \'go\'}' +, 'Hash' => [ { '' => '{ foo => \'bar\', baz => \'bof\' }', 'KV' => [ { '' => ' foo => \'bar\'', 'Value' => [ '\'bar\'' ], 'Key' => [ 'foo' ] }, { '' => 'baz => \'bof\' ', 'Value' => [ '\'bof\'' ], 'Key' => [ 'baz' ] } ] }, { '' => '{bing => \'go\'}', 'KV' => [ { '' => 'bing => \'go\'', 'Value' => [ '\'go\'' ], 'Key' => [ 'bing' ] } ] } ] };

      print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});
      thanks you Cdarke your code works .
      but i acctually i try to pass a variable to it. how should i correct it?

      many thanks

      use strict; use warnings; use Data::Dumper; my $str = "{file => 'file1', desc => 'test'}, {file => 'file12', desc + => 'test2'}" my $string = $str; my @array_of_hashes; my @array_of_hashes; my @hashes = $string =~ /(\{.*?\})/g; for my $hashstr (@hashes) { my @keys = $hashstr =~ /(\w+)\s*=>/g; my @values = $hashstr =~ /=>\s*\'(\w+)\'/g; my %hash; @hash{@keys} = @values; push @array_of_hashes, \%hash; } print "Pragma: no-cache\n"; print "Content-type:text/html\n\n"; print Dumper(\@array_of_hashes);




      Dear cdarke

      your code is indeed work . thank you very much .

      how ever i found when the value contain space or be empty
      value or even Japanese or Chinese fout. it will produce undef and
      eventually lead to mis match of key and value?



      for example: below case are non work



      desc => 'test no work'
      desc => ''
      desc => 'japanese_fond_here_non_work'


      Could you help me a a bit more this time?
Re: Convert string to array of hashes
by moritz (Cardinal) on Aug 08, 2009 at 12:19 UTC
    You can use eval, but be aware that is a security risk if your string contains something other than such data structures.
Re: Convert stirng to array of hashes
by ikegami (Patriarch) on Aug 08, 2009 at 15:27 UTC
    Is that JSON? Is that YAML? Is that Perl code? There's insufficient information in your post to make the distinction. eval would be wrong for the first two.
Re: Convert stirng to array of hashes
by Anonymous Monk on Aug 08, 2009 at 13:04 UTC