/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:
#!/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 },
} );
-
tye
(but my friends call me "Tye") |