The following parses the data into a structure somewhat like the one you describe. It doesn't insert extranious single element arrays and it is not robust against nested quoted strings, but it may be a useful starting point for your actual application.
use warnings; use strict; use Data::Dump::Streamer; my @libs; local $/ = 'libname='; # Read a record at a time while (<DATA>) { chomp; next if ! length; # Skip blank lines s/\n|\r/ /g; # Remove conventional line end characters next if ! s/(\S+)\s*//; my $str = $_; my %record; $record{libname} = $1; while ($str =~ /=/) { # Process an option last if ! ($str =~ s/\s*(\S+?)\s*=\s*//); my $opName = $1; my $opValue; if ($str =~ s/^\s*"([^"]*)"\s*//) { # Complicated option value $opValue = parseSubOps ($1); } elsif ($str =~ s/\s*(\S+)\s*//) { # Simple option $opValue = $1; } $record{$opName} = $opValue; } push @libs, {%record}; } Dump (\@libs); sub parseSubOps { my $str = shift; my %subOps; while ($str =~ /=/) { # Process a sub-option last if ! ($str =~ s/\s*(\S+)\s* = \s*\(\s* ([^)]*?) \)\s*//x) +; my $name = $1; my @values = $2 =~ /'([^']*?)'/g; $subOps{$name} = \@values; } return \%subOps; } __DATA__ libname=foo pathname=/path/to/metadata/foo owner=someuser libaclinheri +t=no dynlock=no roptions=" datapath=('/data/path1' '/data/path2' '/data/path3' ...) indexpath=('/indx/path1' '/indx/path2' '/indx/path3' ...) workpath=('/work/path1' '/work/path2' '/work/path3' ...) metapath=('/meta/path1' '/meta/path2' '/meta/path3' ...)"; libname=bar pathname=/path/to/metadata/bar owner=someuser libaclinheri +t=no dynlock=no roptions=" datapath=('/data/path1' '/data/path2' '/data/path3' ...) indexpath=('/indx/path1' '/indx/path2' '/indx/path3' ...) workpath=('/work/path1' '/work/path2' '/work/path3' ...) metapath=('/meta/path1' '/meta/path2' '/meta/path3' ...)"; libname=foobar pathname=/path/to/metadata;
Prints:
$ARRAY1 = [ { dynlock => 'no', libaclinherit => 'no', libname => 'foo', owner => 'someuser', pathname => '/path/to/metadata/foo', roptions => { datapath => [ '/data/path1', '/data/path2', '/data/path3' ], indexpath => [ '/indx/path1', '/indx/path2', '/indx/path3' ], metapath => [ '/meta/path1', '/meta/path2', '/meta/path3' ], workpath => [ '/work/path1', '/work/path2', '/work/path3' ] } }, { dynlock => 'no', libaclinherit => 'no', libname => 'bar', owner => 'someuser', pathname => '/path/to/metadata/bar', roptions => { datapath => [ '/data/path1', '/data/path2', '/data/path3' ], indexpath => [ '/indx/path1', '/indx/path2', '/indx/path3' ], metapath => [ '/meta/path1', '/meta/path2', '/meta/path3' ], workpath => [ '/work/path1', '/work/path2', '/work/path3' ] } }, { libname => 'foobar', pathname => '/path/to/metadata;' } ];
In reply to Re: Parsing a complex config file
by GrandFather
in thread Parsing a complex config file
by solitaryrpr
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |