Greetings,
I'm not sure if this is a real cool use, but with this class you can specify any regex for a standard parser tool as well as any callback in string form (pretty useful if you want to do all of that in a configuration file under version management)

I have some serious doubts about the way I used eval in this code so I would welcome feedback on how to do it better. I looked over the forum for ways to handle the storing of substitution regex and back references but what I found I felt I did not understand enough to re use properly so if you feel like engraving it into my forehead so I can get it feel free to do so (I'm refering to this node and that one

now here is the code :

package Security::Monitoring::Logs::Normalization::Parser; use 5.006; use strict; use warnings; use Carp; use Security::Monitoring::Utils; =head1 NAME Normalization::Parser =head1 VERSION Version 0.01 =cut our $VERSION = '0.01'; =head1 SYNOPSIS my %params = { regex=>'single quoted string regex to be evalued', name=>"my_parser_name", tag=>"log_type_or_anything", callback_ref=>'string containing a sub that will be called whe +never matching does or does not happen,like writing to a file handle +' } my $instance = $class->init(\%params); open my $fh, '<','to_be_parsed.log'; $instance->parse($fh); the callback ref should use one input and one output, see tests fo +r examples =head1 DESCRIPTION this module provides a class for the parser instance that will be +in charge of normalizing each logs and store the metadata =head1 SUBROUTINES/METHODS =head2 new instance creator =cut sub new { my $class = shift; my $params = shift; if (!defined($params)){ croak("params are not defined!\n"); } my $self = {}; bless $self,$class; $self->_init($params); return $self; } =head2 _init instance initialisation subroutine =cut sub _init{ my $self = shift; my $params = shift; #makes code from the callback string my $callback = eval $params->{callback_ref}; $params->{callback_ref} = $callback; my @keys = keys %{$params}; foreach my $key (@keys){ $self->{$key} = $params->{$key}; } } =head2 parse starts parsing from a file handle ref =cut sub parse{ my ($self,$input,$output) = @_; if (!defined($self->{regex})|| !defined($input) || !defined($outpu +t)|| !defined($self->{callback_ref})){ croak "sorry, my caller must have a defined regex and my input + and output have to be defined, the caller callback has to be too"; } else{ my $reghash_ref = $self->{regex}; while(<$input>){ my $line = $_; my $result = undef; eval '$result = $line =~ '.$self->{regex}; $self->{callback_ref}($result,$line,$output); } } } 1; # End of Security::Monitoring::Logs::Normalization::Parser

And, as usual, the tests, iirc its almost 100% cover

#!perl -T use 5.006; use strict; use warnings; use Test::More; use Test::Exception; use Security::Monitoring::Logs::Normalization::Parser; use diagnostics; BEGIN { plan tests => 9; use_ok( 'Security::Monitoring::Logs::Normalization::Parser' ) || p +rint "Bail out!\n"; } my $class = 'Security::Monitoring::Logs::Normalization::Parser'; diag( "Testing Parser module $Security::Monitoring::Logs::Normalizatio +n::Parser::VERSION, Perl $], $^X" ); my $callback = 'sub { my($result,$input,$output) = @_; if ($result){ print $output $input; } }'; my $params ={name=>"dummy",tags=>"silly",regex=>'m/tata/',callback_ref +=>$callback}; our $parser = $class->new($params); dies_ok(sub{my $new = $class->new(undef)},"new dies when params undef" +); ok(defined($parser),'my dummy parser correctly created'); my $input = "tata\ntoto\ntutu"; my $output; open my $fh_input, '<',\$input; open my $fh_output,'>',\$output; $parser->parse($fh_input,$fh_output); is($output,"tata\n",'match parsing works'); $parser->{regex} = 's/(tata)/$1tutu/'; open $fh_output, '>',\$output; seek $fh_input,0,0; $parser->parse($fh_input,$fh_output); is($output,"tatatutu\n","substitution parsing works"); dies_ok(sub{ $parser->parse(undef,$fh_output)},"parse dies with undefi +ned input"); dies_ok(sub{$parser->parse($fh_input,undef)}, "parse dies with undefin +ed output"); dies_ok(sub {$parser->{regex} = undef;$parser->parse($fh_input,$fh_output)},"parse dies with undefined regex"); $parser->{regex} = 'm/tata/'; dies_ok(sub {$parser->{callback_ref} = undef; $parser->parse($fh_input,$fh_output); },"parser dies with undefined callback"); close $fh_output;
Thank you for your feedback :)

In reply to Generic Parsing class with callback by QuillMeantTen

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.