1

Here is my scenario:

If the text contains dirty or rotten in any position, no matches should be found regardless of matching patterns.

If the text without dirty or rotten contains either red, greed, or yellow followed by apple, pear or peach it would be a match.

Here is what I have tried:

(?:.+(?:[^(dirty)|(rotten)].{1,30}))(?:green|red|yellow).(?:apple|peach|pear)(?:(?!(dirty|rotten))(?:$))

These should match: I have an green apple I have a yellow peach I have red and green apples

These should not: I have a dirty red apple I have a green peach that is dirty I have a yellow dirty apple

JBone
  • 1,724
  • 3
  • 20
  • 32
Ozzie
  • 11
  • 1
  • It is helpful to use formatting for code and other literal strings. – varontron Jan 17 '20 at 18:44
  • This part: [^(dirty)|(rotten)] does NOT do, what you think (it's a character group), it matches any character not mentioned (not the words). – Poul Bak Jan 18 '20 at 15:37

1 Answers1

0

You might use the negative lookahead at the start checking the there is no occurrence of dirty or rotten.

Then match either red, green or yellow followed by apple peach or pear and place word boundaries \b around the words to prevent them being part of a larger word.

^(?!.*\b(?:dirty|rotten)\b).*?\b(?:red|green|yellow)\b.*\b(?:apple|peach|pear)\b.*$

Regex demo


If red, green or yellow can not occur before apple, peach or pear you could make use of a tempered greedy token approach (?:(?!(?:apple|peach|pear)).)* matching any character except an newline without matching one of the options.

^(?!.*\b(?:dirty|rotten)\b)(?:(?!(?:apple|peach|pear)).)*(?:red|green|yellow)\b.*\b(?:apple|peach|pear)\b.*$

Regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70