Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks

I would like to ask, if 1 regex can do a a filtering like that:
1. A string need to begin with a specfic string
2. in the middle it can't have a specific string
3. it match a pattern at the last.

Replies are listed 'Best First'.
Re: Regexp problem: filtering
by moritz (Cardinal) on Mar 12, 2008 at 08:59 UTC
    You can test for the start of the string with \A, so m/\Afoo/ checks if $_ starts with foo.

    You can match the end of the string witz \z, so if you have want to check if a string ends with bar, use m/bar\z/.

    If you want to exclude a string from your search, you can use the negative lookahead: m/^(?!.*foo).*bar/ matches a string that contains a bar but no foo.

    You can put it all together: to match a string that begins with foo, ends with bar and doesn't contain baz you can use this regex: m/\Afoo(?!.*baz).*bar\z/s

    Most of the time it's easier to put all that into different regexes:

    if (m/^foo/ && m/bar$/ && !m/baz/){ ... }

    See perlre for details

Re: Regexp problem: filtering
by hipowls (Curate) on Mar 12, 2008 at 09:46 UTC

    Given that they are constant strings that you are checking then your performance will be better splitting the test into three parts, substr to check for the start and end strings and index to check for the absence of the middle string. This is some benchmarking I did.

    #!/net/perl/5.10.0/bin/perl use strict; use warnings; use Benchmark qw(cmpthese); my $str1 = join '', 'a' .. 'z'; my $str2 = join '', 'a' .. 'l', 'baz', 'm' .. 'z'; my $str3 = join '', 'a' .. 'z', 'a'; my $rx = qr/\Aabc(?!.*baz).*xyz\z/ms; cmpthese( -1, { regex_match => sub { $str1 =~ /$rx/ }, index_match => sub { substr( $str1, 0, 3 ) eq 'abc' && substr( $str1, -3 ) eq 'xyz' && index( $str1, 'baz' ) == -1; }, } ); cmpthese( -1, { regex_fail1 => sub { $str2 =~ /$rx/ }, index_fail1 => sub { substr( $str2, 0, 3 ) eq 'abc' && substr( $str2, -3 ) eq 'xyz' && index( $str2, 'baz' ) == -1; }, } ); cmpthese( -1, { regex_fail2 => sub { $str3 =~ /$rx/ }, index_fail2 => sub { substr( $str3, 0, 3 ) eq 'abc' && substr( $str3, -3 ) eq 'xyz' && index( $str3, 'baz' ) == -1; }, } ); __END__ Rate regex_match index_match regex_match 337317/s -- -73% index_match 1228799/s 264% -- Rate regex_fail1 index_fail1 regex_fail1 362337/s -- -70% index_fail1 1226609/s 239% -- Rate regex_fail2 index_fail2 regex_fail2 865569/s -- -48% index_fail2 1653160/s 91% --

Re: Regexp problem: filtering
by jwkrahn (Abbot) on Mar 12, 2008 at 08:57 UTC
    Not unless there is either nothing between 1 and 2 or nothing between 2 and 3.    Oops I cede to moritz's more correct answer.    :-)
Re: Regexp problem: filtering
by halfcountplus (Hermit) on Mar 12, 2008 at 14:44 UTC