Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

POE::Filter::Line InputRegexp Help Requested

by cmv (Chaplain)
on Aug 18, 2010 at 13:57 UTC ( #855783=perlquestion: print w/ replies, xml ) Need Help??
cmv has asked for the wisdom of the Perl Monks concerning the following question:


I'm trying to use POE::Wheel::Followtail and POE::Filter::Line to deliver messages to me from a file with a specific format. I'm trying to build the correct InputRegexp to get this to happen for me, but am having problems understanding why my attempts are not working. None of my attempts work, and the uncommented one gets me closest (but will also match things I don't want it to).

The attached script shows an example of the data format I have, and my stumbling through learning about InputLiteral and InputRegexp to try and get things to work as I'd like. A working script should provide output as follows:

Msg(1): Message 1 Line 1 Msg(2): Message 2 Line 1 Message 2 Line 2 Msg(3): Message 3 Line 1 Message 3 Line 2 Message 3 Line 3 Msg(4): Message 4 Line 1 Message 4 Line 2 Message 4 Line 3 Message 4 Line 4 Msg(5): Message 5 Line 1 Message 5 Line 2 Message 5 Line 3 Message 5 Line 4
On a side note, I'm wondering about message 6. In this case (assuming the file doesn't grow anymore) message 6 will never be output. Is that correct or is there some way to get it to assume message 6 is a single line and print it out if the file doesn't grow for say, 2 seconds? Also, if that could be done, then what would be a logical way to handle things when the assumption is wrong?



Update: Added readmore tags

use strict; use warnings; use POE qw(Wheel::FollowTail Filter::Line); my $tmpfile = "/tmp/data$$"; my $i=1; POE::Session->create( inline_states => { _start => sub { $_[HEAP]{tailor} = POE::Wheel::FollowTail->new( Seek=>0, Filename => "$tmpfile", InputEvent => "got_log_line", Filter => POE::Filter::Line->new( #InputLiteral=>"\n+++", #InputRegexp=>"\n\\+\\+\\+", InputRegexp=>"\n[+*][+*][+*]\\s+", #InputRegexp=>"\n(\\*\\*\\*)|(\\+\\+\\+)\\s+", #InputRegexp=>"\n(\\+\\+\\+)|(\\*\\*\\*)\\s+", ), ); }, got_log_line => sub { print "Msg($i):\n$_[ARG0]\n"; $i++ } } ); open(DATA, ">$tmpfile") || die "Can't open $tmpfile"; print DATA " *** Message 1 Line 1 +++ Message 2 Line 1 Message 2 Line 2 *** Message 3 Line 1 Message 3 Line 2 Message 3 Line 3 +++ Message 4 Line 1 Message 4 Line 2 Message 4 Line 3 Message 4 Line 4 +++ Message 5 Line 1 Message 5 Line 2 Message 5 Line 3 Message 5 Line 4 *** Message 6 Line 1"; close(DATA); POE::Kernel->run(); exit;

Comment on POE::Filter::Line InputRegexp Help Requested
Select or Download Code
Replies are listed 'Best First'.
Re: POE::Filter::Line InputRegexp Help Requested
by bingos (Vicar) on Aug 19, 2010 at 08:46 UTC
    InputRegexp may be used in place of InputLiteral to recognize line ter +minators based on a regular expression.

    I believe this is the important point.

    I think what you trying to achieve is beyond what POE::Filter::Line can do by itself. Maybe POE::Filter::Block would be a better?

    The other option is to use POE::Filter::Line with a custom filter in a stackable filter POE::Filter::Stackable.

Re: POE::Filter::Line InputRegexp Help Requested
by james2vegas (Chaplain) on Aug 18, 2010 at 22:36 UTC
    I normally don't use POE for such things, I use the read and write queues (with the push_read and push_write methods) of an AnyEvent::Handle. Since AnyEvent works with POE, perhaps you can combine the two, unless you are required to use POE alone.
Re: POE::Filter::Line InputRegexp Help Requested
by cmv (Chaplain) on Aug 19, 2010 at 14:00 UTC
    james2vegas++ Thanks for the pointer. Using AnyEvent::Handle looks like it would give me lots of possibilities, particularly if I wanted to chase down Message 6 in some way. That's a bit beyond my current scope right now, but it's a definite candidate for the evolution path.

    bingos++ It's good grounding to reinforce what POE::Filter::Line was designed to do. I sort of scooched beyond that by utilizing InputRegexp to do simple message parsing. It seems to work well for what I want, but I'm confused about why some of the regexp's don't work as I expect them to...

    One specific thing that is particularly confusing to me is why using either of the following two lines give different results.

    InputRegexp=>"\n(\\*\\*\\*)|(\\+\\+\\+)\\s+", InputRegexp=>"\n(\\+\\+\\+)|(\\*\\*\\*)\\s+",
    Now granted, my regexp brain cells still need work, but shouldn't I be getting the same results using either? Maybe I'm I not using this correctly?



Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://855783]
Approved by Corion
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2016-02-08 03:33 GMT
Find Nodes?
    Voting Booth?

    How many photographs, souvenirs, artworks, trophies or other decorative objects are displayed in your home?

    Results (266 votes), past polls