1

I thought I knew a thing or two... then I met RegEx. So what I am trying to do is a multistring negative look-ahead? Is that a thing? Basically I want to find when a 3rd string exists BUT two precursory strings do NOT.

(?i:<!((yellow thing)\s(w+\s+){0,20}(blue thing))\s(\w+\s+){0,100}(green thing))

Target String:

  • Here we have a yellow thing. Here we have a blue thing. Clearly the green thing is best though. (Should NOT match)
  • You wanna buy some death sticks? I have a green thing. (MATCH)
  • We are on a yellow thing submarine? Look at that green thing over there! (MATCH)
Brenticus
  • 9
  • 3
  • You ruined the lookbehind and turned it into an option group with inline modifier. Try `(?<!yellow thing\W*(\w+\W+){0,20}\W*blue thing\W*(\w+\W+){0,100})green thing`. Word boundaries can be added around the "thing"s to match whole words only. – Wiktor Stribiżew Jul 19 '16 at 06:03

2 Answers2

0

Try this:

^(?:(?!\byellow thing\b.*?\bblue thing\b).)*\bgreen thing\b

Demo: https://regex101.com/r/dL0uZ1/2

Explanation:

  • look for the "green thing" (\b's around it mark word boundaries)
  • but only if it is not preceded by the two other strings as seen from the beginning of the text line hence ^ followed by the "string not containing a pattern" pattern (see Regular expression to match a line that doesn't contain a word? for more details on it).
Community
  • 1
  • 1
Dmitry Egorov
  • 9,542
  • 3
  • 22
  • 40
0

I understand the question as an attempt to only match c inside the string, not the whole string, using the negative lookbehind of infinite width.

You spoiled the lookbehind structure by inserting i: right after ?, and you missed the fact that there can be non-word characters in-between "words".

Thus, you need

(?<!yellow thing\W*(?:\w+\W+){0,20}\W*blue thing\W*(?:\w+\W+){0,100})green thing

See the regex demo where I added numbers to emulate the number of optional words in-between matches.

NOTE: You may add word boundaries around things to match them as whole words only - that depends on your requirements.

Also, you may turn all capturing groups (\w+\W+) into non-capturing to keep these group stacks free (no need to keep track of what these groups capture, right?) If you need to capture them, keep capture groups intact.

Results:

enter image description here

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Ah! Very nice. I see the error of my ways. Thank you sir. Also I used the ?i because it ignores case. (?i:(?<!yellow thing\W*(\w+\W+){0,20}\W*blue thing\W*(\w+\W+){0,100})green thing) – Brenticus Jul 19 '16 at 13:44
  • You may just use `RegexOptions.IgnoreCase` flag when using the pattern with `Regex` methods. – Wiktor Stribiżew Jul 19 '16 at 13:44