#!/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 }, } );