max_reformation_duration=300
cfs_online_timeout_changes=200
max_configured_packages=100
node:nodeA|name=nodeA
node:nodeA|status=up
node:nodeA|interface:lan900|name=lan900
node:nodeA|interface:lan900|status=up
node:nodeA|interface:lan900|ip_address:IP_A|name=IP_A
node:nodeA|interface:lan900|ip_address:IP_A|netmask=255.255.255.0
node:nodeA|interface:lan901|name=lan901
node:nodeA|interface:lan901|status=up
node:nodeA|interface:lan901|ip_address:IP_C|name=IP_C
node:nodeA|interface:lan901|ip_address:IP_C|netmask=255.255.255.0
node:nodeA|subnet:SUBNET_A|name=SUBNET_A
node:nodeA|subnet:SUBNET_A|status=up
node:nodeA|subnet:SUBNET_B|name=SUBNET_B
node:nodeA|subnet:SUBNET_B|status=up
node:nodeB|name=nodeB
node:nodeB|status=up
node:nodeB|interface:lan900|name=lan900
node:nodeB|interface:lan900|status=up
node:nodeB|interface:lan900|ip_address:IP_B|name=IP_B
node:nodeB|interface:lan900|ip_address:IP_B|netmask=255.255.255.0
node:nodeB|interface:lan901|name=lan901
node:nodeB|interface:lan901|status=up
node:nodeB|interface:lan901|ip_address:IP_D|name=IP_D
node:nodeB|interface:lan901|ip_address:IP_D|netmask=255.255.255.0
node:nodeB|subnet:SUBNET_A|name=SUBNET_A
node:nodeB|subnet:SUBNET_A|status=up
node:nodeB|subnet:SUBNET_B|name=SUBNET_B
node:nodeB|subnet:SUBNET_B|status=up
####
%config = {
max_reformation_duration => 300,
cfs_online_timeout_changes => 200,
max_configured_packages => 100,
node => {
nodeA => {
name => nodeA,
status => up,
interface => {
lan900 => {
name => lan900,
status => up,
ip_adress => {
IP_A => {
name => IP_A,
netmask => 255.255.255.0,
},
},
},
lan901 => {
name => lan901,
status => up,
ip_adress => {
IP_C => {
name => IP_C,
netmask => 255.255.255.0,
},
},
},
},
subnet => {
SUBNET_A => {
name => SUBNET_A,
status => up,
},
SUBNET_B => {
name => SUBNET_B,
status => up,
},
},
},
nodeB => {
name => nodeB,
status => up,
interface => {
lan900 => {
name => lan900,
status => up,
ip_adress => {
IP_A => {
name => IP_B,
netmask => 255.255.255.0,
},
},
},
lan901 => {
name => lan901,
status => up,
ip_adress => {
IP_C => {
name => IP_D,
netmask => 255.255.255.0,
},
},
},
},
subnet => {
SUBNET_A => {
name => SUBNET_A,
status => up,
},
SUBNET_B => {
name => SUBNET_B,
status => up,
},
},
},
},
}
####
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
sub read_input {
open(my $io, '<', 'input.txt') or die $!;
return <$io>;
}
my @lines = read_input();
my %config;
my $hashref = \%config;
# stack of hash references
my @ref;
# count of | characters in a respective line
my $level = 0;
# count of | characters in the previous line
my $prev_level = 0;
my $key;
my $fkey;
for (@lines) {
chomp;
my @f = split(/\|/);
$level = @f - 1;
if ($level == 0) {
my @f = split(/=/);
$hashref->{ $f[0] } = $f[1];
} else {
my @q = split(/:/, $f[$level - 1]);
if ($key && $level <= $prev_level) {
if (/\Q$key\E/) {
my @f = split(/=/, $f[$level]);
$hashref->{ $f[0] } = $f[1];
$prev_level = $level;
} elsif (/\Q$fkey\E/) {
$hashref = $ref[-1];
$hashref->{$q[1]} = {};
$hashref = $hashref->{$q[1]};
$key = join(':', @q);
$prev_level = $level;
redo;
} else {
pop @ref;
if ($level < $prev_level) {
my $diff = $prev_level - $level;
while ($diff--) { pop @ref; pop @ref; }
}
$hashref = pop @ref;
$key = '';
$prev_level = $level;
redo;
}
} else {
if (exists $hashref->{$q[0]}) {
push @ref, $hashref;
$hashref->{$q[0]}->{$q[1]} = {};
$hashref = $hashref->{$q[0]}->{$q[1]};
} else {
push @ref, $hashref;
$hashref->{$q[0]} = {};
$hashref = $hashref->{$q[0]};
push @ref, $hashref;
$hashref->{$q[1]} = {};
$hashref = $hashref->{$q[1]};
}
$key = join(':', @q);
$fkey = $q[0];
$prev_level = $level;
redo;
}
}
}
print Dumper( \%config );
####
$VAR1 = {
'cfs_online_timeout_changes' => '200',
'max_configured_packages' => '100',
'max_reformation_duration' => '300',
'node' => {
'nodeA' => {
'interface' => {
'lan900' => {
'ip_address' => {
'IP_A' => {
'name' => 'IP_A',
'netmask' => '255.255.255.0'
}
},
'name' => 'lan900',
'status' => 'up'
},
'lan901' => {
'ip_address' => {
'IP_C' => {
'name' => 'IP_C',
'netmask' => '255.255.255.0'
}
},
'name' => 'lan901',
'status' => 'up'
}
},
'name' => 'nodeA',
'status' => 'up'
},
'subnet' => {
'SUBNET_A' => {
'name' => 'SUBNET_A',
'status' => 'up'
},
'SUBNET_B' => {
'name' => 'SUBNET_B',
'status' => 'up'
}
}
}
};