http://qs321.pair.com?node_id=369380


in reply to Can't match negated words.

Hi folks, Thanks for pointing that out Hugo. I'm currently trying to extend it so that for the line
/* sdfthrow OtherException
prints 'Opening extended comment' but does not for the line
throw new Exception() /* asdfasdf
Basically so long as the '/*' hasn't been preceeded with a throw then it should print out opening the comment. I've got the following expression in place.
if ($line =~ /^.*\/\*((?:(?<!throw)).*$/ ) { debug("Opening extended comment"); }
Is my understanding this expression correct? Would folks mind if I explain what I think is going on from left-right?

/^ matches the start of the $line string

.* says that the start can be proceeded by any number of characters

\/\* matches the '/*' string

(?:(?<!throw)) means so long as /* isn't preceeded in the string by the word throw $line still matches

.*$ means that any number of characters can proceed the /* upto the end of the line

My understanding's obviously incorrect cos eh.. it don't work for a lad. Any help would be greatly appreciated, Mark.

Replies are listed 'Best First'.
Re: Can't match negated words.
by Abigail-II (Bishop) on Jun 24, 2004 at 15:19 UTC
    Regexes match from left to right. So, if you first say "match /*", and then say, "don't match throw", it's *not* going to exclude "/*"'s that are preceeded with "throw". In fact, you haven't given any requirements for what should preceed "/*".

    Ignoring the fact that you don't specify what should happen on a line like this:

    /* throw /*
    you might want to use something like:
    m!^(?:(?!throw).)*/[*]!s
    although that can probably be optimized (and the more you know about where you are going to match against, the more possibilities for optimizing there are).

    Abigail

      Hi Abigail,

      I'd like to match the first '/*' and check that there's no

      throw declared before it.

      I think it should look something like this?

      m!^/[*].*?(?:(?!throw).)*/[*]!s

      I can't really understand what the '.)*' means after the throw?

      You could explain it briefly could you? Thanks,

      Mark.

        I think it should look something like this?
        No, I think not, for exactly the reasons I stated. But if you're convinced you're right, by all means, use your regex. It's not my program after all.
        I can't really understand what the '.)*' means after the throw?
        It doesn't make any sense at all. It's like asking what the "nd wh" in your question means. A dot means "match any character", and a star means "match the preceeding unit one or more times", but the closing parenthesis is belongs to the matching opening one.

        However, if you don't understand the most basic regexp tokens, I urge you to first learn basic regexes, before continuing asking questions.

        Abigail

Re^2: Can't match negated words.
by Roy Johnson (Monsignor) on Jun 24, 2004 at 15:24 UTC
    Putting dot-star next to an anchor is pointless. Just throw out the anchor and the dot-star. That leaves you with:
    /\/\*((?:(?<!throw))/
    You've got capturing parentheses around non-capturing parentheses, around a negative lookbehind. You only need the parens for the negative lookbehind:
    /\/\*(?<!throw)/
    Ok, now you've matched "/*", and at that point, you're looking back to ensure that what comes before you isn't "throw". It can't be, because it ends in "/*". You can't really check everything up to the "/*" with a negative lookbehind, because negative lookbehinds can't be variable-length, and your line can be. You can do it with negative lookahead:
    if ($line =~ /^(?:(?!throw).)*?\/\*/)
    That will be any number of characters that isn't the start of "throw", followed by "/*". The *? makes it take the first "/*" rather than the last.

    Please see this node about YAPE::Regex::Explain for a helpful module.


    We're not really tightening our belts, it just feels that way because we're getting fatter.