diff options
| author | Packy Anderson <packy@cpan.org> | 2024-03-10 22:16:28 -0400 |
|---|---|---|
| committer | Packy Anderson <packy@cpan.org> | 2024-03-10 22:16:28 -0400 |
| commit | f3bb477b370ef28264813c6cb8e2590030faebf0 (patch) | |
| tree | 6c5ad56dd0c1de442755f015611bd755203d27c3 | |
| parent | 0654d63d1d6cab280ac6f9d817431d0431349a31 (diff) | |
| download | perlweeklychallenge-club-f3bb477b370ef28264813c6cb8e2590030faebf0.tar.gz perlweeklychallenge-club-f3bb477b370ef28264813c6cb8e2590030faebf0.tar.bz2 perlweeklychallenge-club-f3bb477b370ef28264813c6cb8e2590030faebf0.zip | |
Challenge 259 late solution by Packy Anderson
* Perl - Task 2
| -rwxr-xr-x | challenge-259/packy-anderson/perl/ch-2.pl | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/challenge-259/packy-anderson/perl/ch-2.pl b/challenge-259/packy-anderson/perl/ch-2.pl new file mode 100755 index 0000000000..5be4e1fb4e --- /dev/null +++ b/challenge-259/packy-anderson/perl/ch-2.pl @@ -0,0 +1,71 @@ +#!/usr/bin/env perl +use v5.38; + +my $ID = qr/ (?<ID> \w+) /x; +my $FIELD = qr/ (?<FIELD> \w+) /x; +my $NUMBER = qr/ (?<NUMBER> \d+ [ \. \d+ ]? ) /x; +my $STRING = qr/ (?<STRING> ([^"] | \\ | \\\" )+ ) /x; + +my $QUOTED_STRING = qr/ (?<QUOTED_STRING> " $STRING " ) /x; +my $FIELD_VALUE = qr/ $FIELD \s* = \s* ( $NUMBER | $QUOTED_STRING ) \s* /x; +my $FIELD_VALUES = qr/ (?<FIELD_VALUES> (?: $FIELD_VALUE \s* )* ) /x; + +# negative lookbehind and negative lookahead +my $TEXT = qr/ (?<TEXT> (?<! {% ) .+ (?! %} ) ) /x; +my $LINE = qr/ (?<LINE> \{% \s* $ID \s* $FIELD_VALUES \s* %\} ) /x; + +my $TOP = qr/^ (?: $LINE | $TEXT ) $/x; + +my $file = shift @ARGV; +open my $fh, '<', $file; + +my %data; +my @ids; +my $in_id; + +while (my $line = <$fh>) { + say 'L: ' . $line; + $line =~ /$TOP/; + + # is there a line with {% ... %} ? + if ($+{LINE}) { + my $id = $+{ID}; + # is the id the end of a block? + if ($id =~ /^ end(\w+) $/x) { # capture after end + if (exists $data{$1}) { # it is! + $id = $1; + undef $in_id; # clear the id we're processing + if ($data{$id}{'text'}) { + # if there's text, remove the final "newline" + $data{$id}{'text'} =~ s/\\n$//; + } + next; # skip to next line of file + } + } + push @ids, $id; # keep list of ids in order + $in_id = $id; # keep track of the current id for text + # initialize base data for this id + $data{$id} = { name => $id }; + # if we have fields... + my $field_values = $+{FIELD_VALUES}; + # loop over field values and store them in the data + while ($field_values =~ /$FIELD_VALUE/g) { + my $value = $+{STRING} ? $+{STRING} : $+{NUMBER}; + if ($+{NUMBER}) { + $value =~ s/\s+$//; # we're picking up trailing spaces + } + $data{$id}->{'fields'}->{ $+{FIELD} } = $value; + } + + } + # if we have non-{% ... %} lines and we have an ID + elsif ($+{TEXT} && $in_id) { + # append a "newline" to the end + $data{$in_id}{'text'} .= $+{TEXT} . "\\n"; + } +} + +use Data::Dumper::Concise; +foreach my $id (@ids) { + print Dumper($data{$id}); +} |
