http://www.perlmonks.org?node_id=368464

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

Hi Monks ! I'm having trouble building a regex that would match as follows:
string starts with chars, contains this, but does not contain that and does not end with whatever A couple of samples:
This regex will match 1 and 2, and correctly skip 3 and 4:

^chars(?!.*that).*this(?!.*that).*

If I include the whatever part, as here

^chars(?!.*that).*this(?!.*that).*(?!.*whatever)$

, sample 2 still matches, whereas this:

^chars(?!.*that).*this(?!.*that).*[^w][^h][^a][^t][^e][^v][^e][^r]$

excludes sample 2 but is horrible...

Am I missing something with the negative lookahead, or is it not possible to do such a thing ?

--
Olivier

Edited by demerphq: Changed </br> to <br />

Replies are listed 'Best First'.
•Re: Problem with negative lookahead at end of string
by merlyn (Sage) on Jun 21, 2004 at 15:45 UTC
    For simplicity sake, you can list a compound "and-ed" condition as a series of null assertions:
    / ^ # anchor so as not to try this at every spot (?= chars ) # stars with chars (?= .*? this ) # contains this (?! .*? that ) # does not contain that (?! .* whatever $ ) # does not end in whatever /xs

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

    update: edited to include additional whitespace for readability
      Nice. "I'd walk a mile for a (Programming Perl) Camel." Had to reach for it to get through that ?!.*? regex! I'm just an old C programmer, learning more than one way to do it...
Re: Problem with negative lookahead at end of string
by delirium (Chaplain) on Jun 21, 2004 at 15:25 UTC
    Despite a processing slowdown, I prefer the readability of splitting criteria like this up into multiple expressions:

    /^chars/ && /this/ && !/that/ && !/whatever$/

      Despite a processing slowdown...

      It depends on the patterns and the string, but it's often faster (and in this case it is faster) to split up the matches into multiple regexes.

Re: Problem with negative lookahead at end of string
by tye (Sage) on Jun 21, 2004 at 15:12 UTC
    /^chars(?!.*that).*this.*(?<!whatever)$/

    If "whatever" is actually a pattern that can match more than a single length of string, then instead use:

    /^chars(?!.*that).*this(?!.*whatever$)/

    And note that the (?!.*that) part doesn't need to be repeated.

    - tye