in reply to Regex'ing backreferences
Here is another alternative:
/foo(.*?)(foo|bar)/ && "bar" ne $2
One functional difference between this and tilly's and japhy's correct solutions is that it can clobber regex variables when the first half matches but the total expression is false. Another is that you can't embed it inside a larger regex.
Which leads me to the "obvious" solution:
/foo(.*?)foo/ && $1 !~ /bar/
And after benchmarking the results are:
Benchmark: running japhy, obvious, tilly, and tye, each for at least 3 CPU seconds (sorted fastest to slowest)... obvious: 3.13 CPU @ 77.96/s (n=244) tilly: 3.41 CPU @ 33.43/s (n=114) tye: 3.29 CPU @ 20.06/s (n=66) japhy: 3.02 CPU @ 10.60/s (n=32)
So the most "optimized" is the slowest and the most obvious is the fastest. I think I know which one I'll use next time. :) Here is the benchmarking code:
- tye (but my friends call me "Tye")#!/usr/bin/perl -w use strict; use Benchmark; my @pat= qw( fooxfoo fooxbar xfooxfoo xfooxbar fooxfoox fooxbarx xfooxfoox xfooxbarx ); my @fill= ( "ba", "fo", "bf", "bafo", "babrar" ); @pat= map { my $fill= $_ x 1000; map { ( my $pat= $_ ) =~ s/x/$fill/g; + $pat } @pat } @fill; sub obvious { /foo(.*?)foo/ && $1 !~ /bar/ and $1 } sub tye { /foo(.*?)(bar|foo)/ && "bar" ne $2 and $1 } sub tilly { /foo((?:(?!bar).)*)foo/ and $1 } sub japhy { m{ foo ( # save to $1 [^b]* # 0 or more non-b characters (?: (?>b+) # 1 or more b's (NO BACKTRACKING!) (?: a(?!r) # an 'a' NOT followed by an 'r' | # or [^a] # a non-a character ) [^b]* # 0 or more non-b characters )* # that whole b... subset, 0 or more times ) foo # and foo }x and $1 } sub checkthese { my( $sub, $hTests )= @_; my %res; for my $meth ( keys %$hTests ) { my $res= $sub->( $hTests->{$meth} ); for( keys %res ) { if( $res ne $res{$_} ) { warn "$meth and $_ disagree!\n"; } } $res{$meth}= $res; } } checkthese( sub { join " ", map { $_[0]->() } @pat }, { tilly => \&tilly, japhy => \&japhy, tye => \&tye, obvious => \&obvious, } ); timethese( -3, { obvious => sub { map obvious(), @pat }, tye => sub { map tye(), @pat }, tilly => sub { map tilly(), @pat }, japhy => sub { map japhy(), @pat }, } );
|
|---|