Hi thanos,
To clarify, the structures I am trying to parse are generated by TreeDumper with $Data::TreeDumper::Displayaddress = 0.
Here is a quick and dirty function I have whipped up which suffices for my possible inputs, but is not quite correct for all possible inputs. Specifically, it will interpret arrays as hashes with keys 0 .. n.
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use feature qw(say);
use Test::Deep qw(eq_deeply);
sub parse_treedump {
my $lines = shift;
my @lines = @$lines;
my %obj;
my @stack;
my $parse_next_line = sub {
my $line = shift @lines;
my $key_indicator = $line =~ /\|-/ ? '|-' : '`-';
my $key_idx = index( $line, $key_indicator );
my $level = @stack;
my $key_level = $key_idx / 3;
if ($key_level < $level) {
pop @stack until $key_level == ($level = @stack);
}
my $current_obj = \%obj;
$current_obj = $current_obj->{$_} foreach @stack;
if ($line =~ /(\w+)\s=\s(.*)$/ && $key_level == $level) {
$current_obj->{$1} = $2 eq 'undef' ? undef : $2;
}
elsif ($line =~ /(\w+)\s\(no\selements\)/) {
$current_obj->{$1} = [ ];
}
elsif ($line =~ /(\w+)\s=$/) {
$current_obj->{$1} = '';
}
elsif ($line =~ /(\w+)/ && $key_level == $level) {
push @stack, $1;
$current_obj->{$1} = { };
}
};
$parse_next_line->() while @lines;
return \%obj
}
my $expected_hash = {
one => 'two',
three => {
four => 'five',
six => 'seven',
eight => {
nine => 'ten'
},
eleven => [ ],
twelve => undef,
},
thirteen => 'fourteen'
};
my $lines = [];
while (<DATA>) {
chomp;
push @$lines, $_;
}
close DATA;
my $output_hash = parse_treedump($lines);
if (eq_deeply($output_hash, $expected_hash)) {
say "OK";
}
1;
__DATA__
|- one = two
|- three
| |- four = five
| |- six = seven
| |- eight
| | `- nine = ten
| |- eleven (no elements)
| `- twelve = undef
`- thirteen = fourteen
As you can see, the TreeDump output in the __DATA__ section gets converted to the expected hash. I would prefer it to work for all possible inputs...
Best, Jim |