Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 978
Selfish Avatar asked Nov 19 '25 16:11

Selfish


2 Answers

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.

like image 191
Wiktor Stribiżew Avatar answered Nov 21 '25 04:11

Wiktor Stribiżew


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

like image 42
Kriggs Avatar answered Nov 21 '25 05:11

Kriggs