in reply to Re: Parsing by indentation
in thread Parsing by indentation

This is exactly what I was looking for. In just one pass ... This is impressive. I tried it out in my code and this works flawlessly against a whole router config. I think I'd like to add a logic to capture parents without a child on the first level and push them in a separate array or in an arrayref inside the structure, but all I can say is WOW. Could you please explain the regex in the while loop ? Otherwhise, I get that you're using the ternary operator to dig deeper ... this solves my challenge in a single line. Respect !

Replies are listed 'Best First'.
Re^3: Parsing by indentation
by tybalt89 (Monsignor) on Oct 24, 2018 at 20:49 UTC

    Same code with expanded regex with comments

    #!/usr/bin/perl # https://perlmonks.org/?node_id=1224600 use strict; use warnings; use Data::Dump 'dd'; my $data = <<'END'; interface XYZ given param1 -> child of "interface XYZ" given param2 -> child of "interface XYZ" given param2.1 -> child of "given param2" given param2.1.1 -> child of "given param2.1" given param2.1.2 -> child of "given param2.1" given param2.2 -> child of "given param2" given param3 -> child of "interface XYZ" given param4 -> child of "interface XYZ" interface SECOND given param5 -> child of "interface SECOND" END my $struct = buildstruct($data); dd $struct; sub buildstruct { my $block = shift; my @answers; while( $block =~ /^ # make sure to start at beginning of a line (wit +h m) (\ *) # match leading spaces of header line (.*) # match rest of line, save as head \n # and match the newline ( (?: # match all following lines with \1 # same whitespace as head \ + # plus at least one more space ( i.e. indented ) .*\n # contents to be looked at later )* # as many as possible ) # save as rest /gmx ) # global, multiline, and extra whitespace { my ($head, $rest) = ($2, $3); $head =~ s/ ->.*//; push @answers, $rest ? { $head => buildstruct($rest) } : $head; } \@answers; }

    I hope this helps :)

    The regex matches each line, gets the indentation space string, then also matches all following lines that are indented that much plus at least one more space.

      Oh yes it does help. Time to read that regex book one more time ... This is just absolutely fantastic ! So much power in a handful of lines !
      /msg tybalt89 After all, I thought I understood the line with the ternary operator, but it seems you're doing some other sort of magic with the double arrow operator. If you don't mind explaining this one too ^_^ ?

        If you are referring to the Here Document, search for '<<EOF' in perlop for more on that. They also get a mention at the end of the quotes in Perl tutorial (and in the replies).

        Also see Here document for a general discussion.


        Give a man a fish:  <%-{-{-{-<

Re^3: Parsing by indentation
by LanX (Saint) on Oct 27, 2018 at 16:21 UTC
    > In just one pass ...

    not really, it's recursive.

    This solution is one-pass.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Oh thanks Rolf ! This is very interesting too, I'll give it a try in the lab later today and let you know ! Best regards ! Luc