in reply to Runtime Regexp Generation

Variables are interpolated into a regex, so you don't need to do a s/THIS/THAT/ on your regex string. Also, its safer if you anchor your regex to the beginning of the string. Here's an example:

my $SOURCE_ADDR = param('source_addr') || '.*?'; my $DEST_ADDR = param('dest_addr') || '.*?'; my $PROTO = param('proto') || '\w+'; my $SOURCE_PORT = param('source_port') || '\d+'; my $DEST_PORT = param('dest_port') || '\d+'; ... my $entry =~ /\A \d+\s+ (\d+)\s+ ($SOURCE_ADDR)\s+ ->\s+ ($DEST_ADDR)\s+ ($PROTO)\s+ ($SOURCE_PORT) \s+>\s+ ($DEST_PORT) /x;

Note that if a user doesn't input one of the above checks, it defaults to matching any valid input for that field. The IP addresses match against '.*?' because I'm too lazy to do it properly--I don't recommend doing it like that in a real program. Also, you might want to remove any whitespace in the user input. Users will likely put in '! TCP', which won't work the same as '!TCP', which is what you want.

----
I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re^2: Runtime Regexp Generation (! .*?)
by tye (Sage) on Apr 14, 2003 at 18:05 UTC

    Please use \S+ instead of .*? so that backtracking won't waste CPU time. Please include \s after ($DEST_PORT) so that you won't match just a prefix of the destination port number.

    I'd add to the above what perlguy recommended:

    my %r= ( source_addr => '\S+', dest_addr => '\S+', proto => '\S+', source_port => '\d+', dest_port => '\d+', ); for my $param ( keys %r ) { my $value= $cgi->param($param) || ""; if( $value =~ s/^!\s*// ) { $r{$param}= "(?!\Q$value\E\s)($r{$param})"; } elsif( $value =~ /\S/ ) { $r{$param}= "(\Q$value\E)"; } else { $r{$param}= "($r{$param})"; } } my $regex= qr/ ^ \d+\s+ (\d+)\s+ $r{source_addr}\s+ ->\s+ $r{$dest_addr}\s+ $r{$proto}\s+ $r{$source_port} \s+>\s+ $r{$dest_port}\s+ /x; while( my $pkt= <DATA> ) { print $pkt if $pkt =~ $regex; }

                    - tye