Matching a string where certain punctuation can exist inside or after the string in regex

Viewed 60

I'm trying to check if a word exists in a string with regex and JavaScript but I'm struggling to get it right.

The matched string can only have a space or nothing before it. The matched string can't have alphanumeric characters or punctuation directly behind it. The matched string can't have alphanumeric characters straight after it, only !, , , ., a space, or nothing. Examples are below!

Currently my regex looks like this:

\w*(?<![^ ])\bHello\b

If you test Hello, Hello!, Hello or Hello it returns true as expected.

If you test .Hello, aHello or Helloa it returns false as expected.

However I have two problems:

  • It returns true if you pass it Hello:, Hello?, Hello) etc. which is not what I want, only !, , , . should be allowed.
  • It does not work for strings with punctuation - I will need to check if the strings D:, :D, and <3 exist in a sentence. I believe this is due to my use of \b

I tried converting \b into what it does under the hood and modifying that, but I couldn't get it to work how I wanted to so I have turned to StackOverflow. I'm OK with having a regex for alphanumeric strings and another one for strings with symbols like : and <. Or if you think it's best to just switch to manual checking with a JavaScript function then that's OK too.

Thanks for any help.

3 Answers

You can use

(?<!\S)Hello(?=[!,.\s]|$)

See the regex demo.

Details

  • (?<!\S) - a left-hand whitespace boundary
  • Hello - some word
  • (?=[!,.\s]|$) - a positive lookahead that requires !, ,, ., whitespace or end of string immediately to the right of the current location.

Without using any lookarounds, Here's my regex.

I had to put the regex in the forEach loop because of the regex's lastIndex property which continues matching from the index of the last match.

Test it out

const regex = /^ ?Hello(?:!|,|\.| |$)/gm;
const trueCases = [" Hello", "Hello!", "Hello", " Hello "];
const falseCases = [".Hello","aHello","Helloa","Hello:","Hello?","Hello)"];

console.log(trueCases.map(trueCase => /^ ?Hello(?:!|,|\.| )?$/gm.test(trueCase)));
console.log(falseCases.map(falseCase => /^ ?Hello(?:!|,|\.| )?$/gm.test(falseCase)));

another version: ^[ ]?[\w:<]+[\!\*. ]?$
explanation with examples are on link: https://regex101.com/r/UtGaHB/1

There are 3 parts to it

  1. ^[ ]? : start (^) with either space or nothing (? means its optional)
  2. [\w:<]+ : all lengths (+) of alphanumeric \w or : or <
  3. [\!\*. ]?$ : end ($) with optional(?) literal characters !, *, . or space

Note that if you specifically want to search Hello (case-sensitive): you would need to change 2nd part

Related