0

With this expression: .*(?=good) i can get:

text is good -> text is

But how to supplement this expression so that it also work in the following case:

text is not good -> NOT MATCH or empty string
Fedor Saenko
  • 138
  • 5

2 Answers2

2

You could use a negative Lookbehind:

.+(?<!not )(?=good)

This ensures that the position where the Lookahead starts is not preceded by "not ".

Demo.

If you want to make sure that the word "not" doesn't appear anywhere before the Lookahead, you may use:

^(?:(?!not).)+(?=good)

Demo.

And if you want to make sure that the word "not" doesn't appear anywhere in the string (even after the Lookahead), you may use:

^(?!.*not).+(?=good)

Demo.

P.S. Use \bnot\b if the rejected "not" must be a whole word (e.g., if you want to allow "knot").

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
ICloneable
  • 613
  • 3
  • 17
  • @Wiktor Is `(?!not).` better than `(?<!not).` in terms of performance or something else? – ICloneable Sep 08 '20 at 22:01
  • @Wiktor Can you please elaborate? Or refer me to a relevant article/post? I tried looking it up but didn't find anything that explains the difference. There's probably something I'm not seeing but as far as I can tell, the lookbehind does the same job. – ICloneable Sep 08 '20 at 22:08
  • See [Tempered Greedy Token - What is different about placing the dot before the negative lookahead](https://stackoverflow.com/a/37343088/3832970). – Wiktor Stribiżew Sep 08 '20 at 22:13
  • @Wiktor Thanks, I did find this post but didn't understand why a Lookbehind wouldn't work the same at first. I think I figured it out now. `(?<!not).+` will match "notgood" because the dot must match what's _after_ the Lookbehind, unlike with the Lookahead where the dot would match the first character. Thanks again! – ICloneable Sep 08 '20 at 22:18
  • *Tempered* dot pattern means the *dot* is tempered, "restricted". The lookbehind does not temper the dot, it just fails its match if some pattern is not present immediately to the left of it. You may use `(?:(?!some pattern).)*`. – Wiktor Stribiżew Sep 08 '20 at 22:20
1

You can assert from the start of the string that it does not contain not good

Then use a non greedy quantifier to match until the first occurrence of good to the right (In case good occurs more than once)

^(?!.*\bnot good\b).*?(?= good\b)

Explanation

  • ^ Start of string
  • (?! Negative lookahead
    • .*\bnot good\b Match not good between word boundaries
  • ) Close lookahead
  • .*? Match any char as least as possible (In case of more occurrences of good, stop before the first)
  • (?= good\b) Positive lookahead, assert good at the right

Regex demo

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