Since \b
meaning is context-dependent, you need to use lookaround-based boundaries in your regex. As you want to match your keywords in between non-word chars, or start/end of string positions, you may use
/(?<!\w)#{Regexp.escape(string)}(?!\w)/
See a Ruby demo
Details
(?<!\w)
- there must not be a word char right before the search string
#{Regexp.escape(string)}
- the search string must be escaped so that all special chars inside were treated as literal chars
(?!\w)
- there must be no word char right after the search word.
Another idea is to use adaptive dynamic word boundaries:
/(?:(?!\w)|\b(?=\w))#{Regexp.escape(string)}(?:(?<=\w)\b|(?<!\w))/
/(?:\B(?!\w)|\b(?=\w))#{Regexp.escape(string)}(?:(?<=\w)\b|(?<!\w)\B)/
The first one is adaptive word boundaries of Type 1 where no special restrictions are imposed on cases where words start or end with special chars, and the second regex only matches words starting or ending with special chars when they are not preceded / followed with a word char.
Feel free to read more about that in Word boundary with words starting or ending with special characters gives unexpected results and watch this YT video of mine with more explanations and a Python demo.