Alex Rivera | Logout

Negative Lookahead Regex greed (why is .*? too greedy)

Asked 2011-05-25T03:11:44.317
20

I'm having trouble understanding the finer details of negative lookahead regular expressions. After reading Regex lookahead, lookbehind and atomic groups, I thought I had a good summary of negative lookaheads when I found this description:

(?!REGEX_1)REGEX_2

Match only if REGEX_1 does not match; after checking REGEX_1, the search for REGEX_2 starts at the same position.

Hoping I understood the algorithm, I cooked up a two-sentence test insult; I wanted to find the sentence without a certain word. Specifically...

Insult: 'Yomama is ugly. And, she smells like a wet dog.'

Requirements:

  • Test 1: Return a sentence without 'ugly'.
  • Test 2: Return a sentence without 'looks'.
  • Test 3: Return a sentence without 'smells'.

I assigned the test words to $arg, and I used (?:(?![A-Z].*?$arg.*?\.))([A-Z].*?\.) to implement the test.

  • (?![A-Z].*?$arg.*?\.) is a negative lookahead to reject a sentence with the test word
  • ([A-Z].*?\.) matches at least one sentence.

The critical piece seems to be in understanding where the regex engine starts matching after processing the negative lookahead.

Expected Results:

  • Test 1 ($arg = "ugly"): "And, she smells like a wet dog."
  • Test 2 ($arg = "looks"): "Yomama is ugly."
  • Test 3 ($arg = "smells"): "Yomama is ugly."

Actual Results:

  • Test 1 ($arg = "ugly"): "And, she smells like a wet dog." (Success)
  • Test 2 ($arg
Edit
Report

1 Answer

3

If you're curious about what Perl is doing with a regex, you can run with the regex debugger:

perl -Dr -e '"A two. A one." =~ /(?![A-Z][^\.]*(?:two)[^\.]*\.)([A-Z][^\.]+\.)/; print ">$1<\n"'

which will generate much output for you to ponder. You will need a Perl built with -DDEBUGGING.

answered 2011-05-25T04:55:50.010

Your Answer