#!/usr/bin/env perl use Benchmark 'cmpthese'; my %ways = ( '3calls' => sub {/a/ && !/b/ && /c/}, code => sub {m:^(?(?{/a/ && !/b/ && /c/})|(?!)):}, pos_look => sub {/(?=.*a)(?!.*b)(?=.*c)/s}, neg_look => sub {/(?!(?!.*a)|(?=.*b)|(?!.*c))/s}, neg_anch => sub {/^(?!(?!.*a)|(?=.*b)|(?!.*c))/s} ); # Minimal check that the regexps do what they're supposed to while (my ($way, $sub)=each %ways) { die "$way failed to match\n" unless ($_ = 'cat') && &$sub; die "$way had a false positive\n" if ($_= 'cab') && &$sub; } print "For matching:\n"; $_="find your cat"; cmpthese(-1, \%ways); print "For non-matching:\n"; $_="don't find a cab"; cmpthese(-1, \%ways); __END__ Rate code neg_look neg_anch pos_anch pos_look 3calls code 674093/s -- -52% -53% -63% -63% -87% neg_look 1417081/s 110% -- -1% -21% -22% -73% neg_anch 1429846/s 112% 1% -- -21% -21% -73% pos_anch 1798791/s 167% 27% 26% -- -1% -66% pos_look 1810887/s 169% 28% 27% 1% -- -66% 3calls 5338256/s 692% 277% 273% 197% 195% -- For non-matching: Rate code neg_anch neg_look pos_anch pos_look 3calls code 674093/s -- -55% -57% -63% -65% -88% neg_anch 1495898/s 122% -- -5% -17% -22% -73% neg_look 1570933/s 133% 5% -- -13% -18% -72% pos_anch 1806441/s 168% 21% 15% -- -5% -67% pos_look 1906963/s 183% 27% 21% 6% -- -65% 3calls 5522908/s 719% 269% 252% 206% 190% --