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

Oh wise ones, Please help before I pull my hair out.
I'm trying to match a pattern not preceed at any time in the string by a ? mark.
Example: http://www.google.com/?stuff=<<merge>>
should not match, whereas
http://<<merge>>.place.com/?blah=blahblah
should match.

From my research though, negative lookbehind only matches the next character. I can't seem to get around this without getting the error: "Look-behind group does not have an obvious maximum length".

(?<![^\?]*\?)<<\w+>>; # was my idea, but it doesn't work.

Replies are listed 'Best First'.
Re: negative lookbehind question
by thundergnat (Deacon) on May 26, 2005 at 20:49 UTC
    No need for a negative look-behind.
    while(<DATA>){ chomp; print; print /^[^?]*<<\w+>>/ ? " - Match\n" : " - No Match\n"; } __DATA__ http://www.google.com/?stuff=<<merge>> http://<<merge>>.place.com/?blah=blahblah

    prints

    http://www.google.com/?stuff=<<merge>> - No Match
    http://<<merge>>.place.com/?blah=blahblah - Match

Re: negative lookbehind question
by dragonchild (Archbishop) on May 26, 2005 at 20:44 UTC
    negative lookbehind only works with a fixed string. You cannot have variable-width negative lookbehind.

    The immediate solution is to reverse your regex, converting a negative lookbehind into a positive lookahead. Regex::Reverse tricky test cases and sexeger are probably good starts on the process.


    • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
    • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
Re: negative lookbehind question
by demerphq (Chancellor) on May 26, 2005 at 20:59 UTC

    Just remember that often its better to reverse the sense of your question with regexes. So if you are asking "match 'foo' not proceeded by ?" turn it into "match anything but '?' followed by 'foo'"

    ---
    $world=~s/war/peace/g

Re: negative lookbehind question
by japhy (Canon) on May 26, 2005 at 23:28 UTC
    While the sexeger solution which I popularized a few years ago is a good solution for this, it's probably overkill. Either do as shown above: /^[^?]*whatever/, or use a technique that is extensible for when the "?" thing is more than just one character in length: /^(?!.*XXX.*$pattern).*$pattern/. That will match $pattern that is not preceded by XXX.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart