Selfish
Selfish

Reputation: 6200

Regexp: substring not followed by character

Assume a regex that should test true for any string containing the substring hello, followed by any string that does not begin with ! or several of !.

Some examples for clarity:

var regExp = /someExpression/;

regExp.test("hello"); // → true
regExp.test("hello!"); // → false
regExp.test("hello!!"); // → false
regExp.test("hello!sdkfjhsdfjkh"); // → false
regExp.test("hellos!dkfjhsdfjkh"); // → true
regExp.test("hello-!"); // → true
regExp.test("hello w34~342`!!"); // → true

I have tried several approaches, here's my best:

var regExp = /.*hello[^!].*/;

This will work well on all cases I can come up with but one: "hello".

In this case, [^!] expects a character.

How can I improve this regex so it tests true for this case as well?

Any kind of help is appreciated.


Edit - bonus points:

The same for hello preceded by a !, so that hello is accepted, but !hello is not.

Upvotes: 3

Views: 336

Answers (3)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

Use a simple alternation with the end of the string:

/hello([^!]|$)/.test(str);

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626896

You need to use a negative look-ahead rather than a negated character class (that still matches, consumes characters):

var regExp = /.*hello(?!!).*/;

See regex demo

See more details at regular-expressions.info:

Negative lookahead is indispensable if you want to match something not followed by something else. When explaining character classes, this tutorial explained why you cannot use a negated character class to match a q not followed by a u. Negative lookahead provides the solution: q(?!u). The negative lookahead construct is the pair of parentheses, with the opening parenthesis followed by a question mark and an exclamation point.

EDIT:

Since JS regex engine does not support look-behind, you need to match (^|[^!])hello (where (^|[^!]) matches either start of string or a symbol other than !) and then do whatever you need to do with it using JS string methods.

Upvotes: 3

Kriggs
Kriggs

Reputation: 3778

With just those cases, negating /hello!/ works just fine:

var regExp = /hello!/;

!regExp.test("hello"); // → true
!regExp.test("hello!"); // → false
!regExp.test("hello!!"); // → false
!regExp.test("hello-!"); // → true
!regExp.test("hello w34~342`!!"); // → true

See: https://regex101.com/r/xI1mG0/1

Upvotes: 1

Related Questions