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;' } ];

DWIM is Perl's answer to Gödel

In reply to Re: Parsing a complex config file by GrandFather
in thread Parsing a complex config file by solitaryrpr

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.